flare-on ctf 2023 第三题mypassion分析

查看 32|回复 2
作者:失神我醉了   
前言
Flare-on每年的ctf都比较有趣,大家可以去试一下,已经办了10届比赛了,官网显示这届最难,因为庆祝比赛10周年。本文就2023的第三题mypassion学习一波逆向,很考验逆向基本功。主要防止忘了,写下来回顾一波。
题目:aHR0cHM6Ly9mbGFyZS1vbi5jb20v
分析
查壳,无壳。


QQ图片20240429182856.png (172.64 KB, 下载次数: 0)
下载附件
2024-5-2 01:02 上传

strings.exe .\mypassion.exe 查看一下字符串,发现了有趣的字符串
C:\send\bitcoin\for\symbols\send\bitcoin\for\symbols\send\bitcoin\for\symbols\send\bitcoin\for\sym.pdb
挖矿的?可能根据某恶意软件修改的。运行了一下程序,后无反应,ok。
IDA分析
_start函数没有反调试,直接来到main函数,可以看到程序运行需要带参数,并且参数要满足一些条件,大致用ida看了一下程序执行流程,没有看到特别有用
的信息,不能一步登天。函数会在运行时会从数据段导shellcode执行,所以我打算动静结合,慢慢分析。首先,参数第7个字母影响VirtualAlloc,第一个字母为'0',   第2,3字母得满足x+4y == 0x127, 用py找一下, 我选择9,C
for x in range(0x20,0x7f):
        for y in range(0x20,0x7f):
                if(x+4*y==0x127):
                        print(chr(x),chr(y))


QQ图片20240429201311.png (48.58 KB, 下载次数: 0)
下载附件
2024-5-2 01:01 上传

所以得到初步参数09CxxRxxxxxxxxx,   然后用windbg动态调试,windbgx.exe .\passion.exe 09CxxRxxxxxxxxx,最好不要用powershell,后面会出现奇怪的问题?导致程序运行失败。cmd没问题
然后我们在virtualAlloc下断点,程序在这儿退出了,看下原因


QQ图片20240429200948.png (39.48 KB, 下载次数: 0)
下载附件
2024-5-2 01:01 上传

用err.exe查看错误值原因,查看相关文档,得到,virtualAlloc最后一个参数得是PAGE_EXECUTE_READWRITE(0x40)。即参数第7个字母得为@。


QQ图片20240429202126.png (40.38 KB, 下载次数: 0)
下载附件
2024-5-2 00:58 上传

修改参数为09CxxR@xxxxxxxxx,继续往下分析


QQ图片20240429211809.png (62.84 KB, 下载次数: 0)
下载附件
2024-5-2 01:00 上传

因为参数13字母会改代码,所以在func1函数入口下个断点,看看这个函数输入是什么,具体代码是干什么的
在偏移1299下断点,可以看到输入参数v39的值是5个'x', 为什么5个,因为v40和v39相邻,v40赋值为'x',高位被清零(汇编代码看会更明白),如图:


QQ图片20240429223211.png (101.83 KB, 下载次数: 0)
下载附件
2024-5-2 00:57 上传

然后我们可以明显看到xabort  56h这行汇编有问题,c678f456 (16进制) ,而78正好是'x'的16进制ASCII码,所以这个是受第13字母影响,我们可以猜测c6后面可能是45(试试),因为上面几行都
是,即字母'E'。所以新参数:09CxxR@xxxxxExxx。也可以用CyberChef进行调试汇编(慢慢猜。。),后面也会用到,因为好几个地方会通过参数影响shellcode。


QQ图片20240429224901.png (122.63 KB, 下载次数: 0)
下载附件
2024-5-2 00:57 上传

那么这段汇编代码在干嘛呢?它好像对后续没什么影响?直接分析很痛苦,动态分析就很舒服,
[color=]我们知道输入是5个'x',即参数8-12位置的值,我们直接在ret
[color=]前f9下断点,看看输出,相关寄存器啥情况,可以发现rsp有东西'
brUc3',正好5位,单步分析的话会发现rsp的字符是临时算出来的。猜测可能和这个字符串比较,暂时不知道有什么用,后面相邻的代码也没用到它,但是我们可以把x改为这个,反正没影响。


QQ图片20240430105630.png (278.41 KB, 下载次数: 0)
下载附件
2024-5-2 00:54 上传

chr((0x74^0x16)) ='b'
chr((0x65^0x17)) ='r'
chr((0x6E^0x3B)) ='U'
chr((0x74^0x17)) ='c'
chr((0x65^0x56)) ='3'
所以新参数:09CxxR@brUc3Exxx
继续往下分析,结合chatgpt和分析,将main函数中后面的函数重命名


QQ图片20240430012408.png (82.41 KB, 下载次数: 0)
下载附件
2024-5-2 00:53 上传

接着进入sub_1400013E0继续分析,ida静态分析一波,可以看到,函数会通过'/'来截取参数,所以修改新参数为:09CxxR@brUc3Exxx/test1/test2/ , 大体分析一下,sub_1400013E0会从数据段写入文件从而创建文件,并且会解密数据段的数据,作为代码执行。


QQ图片20240430013040.png (94.81 KB, 下载次数: 0)
下载附件
2024-5-2 00:53 上传



QQ图片20240430013301.png (71.95 KB, 下载次数: 0)
下载附件
2024-5-2 00:52 上传

sub_1400013E0中间还有个有趣的部分,现在用不到,但后面有影响,即v25变量,v25 = 0x1f + day(系统今天的日期),  v25变量会和数据段进行运算(而这块正属于文件的尾部)。


QQ图片20240430014332.png (65.73 KB, 下载次数: 0)
下载附件
2024-5-2 00:51 上传

继续后面,我们通过动态分析,进入sub_1400013E0动态解密的code,看看这块具体干了什么,在1892哪儿下断点,运行调试器后会发现生成了test1的文件,所以参数会影响文件名。
到达断点后,我们直接单步进入动态分析。在函数前下断点,我们只关心输入和输出。


QQ图片20240430021553.png (260.32 KB, 下载次数: 0)
下载附件
2024-5-2 00:51 上传

根据main函数,可以得到390是retrieve_140002F00,380是strtol_1400071A0,358是ExitProcess,以此类推,最后的3B0是sub_1400018B0函数,所以后面需要分析sub_1400018B0
动态分析后,可以调试得到这段代码在截取test2,并且test2前面得含有数字,并且该数字会转为4为基数的数字,然后与后面数字后面的字符串长度比较,比如这里我选择0x20,转为4为基数为8,所以后面需要8个字符,不然ExitProcess,so修改参数为09CxxR@brUc3Exxx/test1/20testtest/
接着分析sub_1400018B0函数,大体过一遍,该函数会读取之前创建的test1文件,并通过输入参数对该文件进行一些判断。该函数开头和retrieve_140002F00作用一样,在这里它截取第三段,修改参数09CxxR@brUc3Exxx/test1/20testtest/test3/,然后在exitprocess函数下断点,查看一下条件满足


QQ图片20240430112957.png (50.21 KB, 下载次数: 0)
下载附件
2024-5-2 00:49 上传



QQ图片20240430115757.png (218.69 KB, 下载次数: 0)
下载附件
2024-5-2 00:49 上传

所以第三段得改为'?pizza',加‘?’是因为v8[0]没有被比较,跟踪一下v12,v12的逻辑与之前sub_1400013E0函数中v25 变量一样,所以v8[0] =  0x1f + day(今天30)即字符'='
修改参数为09CxxR@brUc3Exxx/test1/20testtest/=pizza/


QQ图片20240430121047.png (39.54 KB, 下载次数: 0)
下载附件
2024-5-2 00:47 上传

接下来我们在下一个exitprocess下断点,可以看到判断逻辑是文件头,所以我们在sub_1400013E0创建文件时忽略了一些东西,我们再去看一下哪里对文件头进行了操作。


QQ图片20240430133209.png (52.09 KB, 下载次数: 0)
下载附件
2024-5-2 00:46 上传

回到sub_1400013E0,文件开头第一段进行了操作,从中提取了数字,所以第一段得包含数字,赋值给了v5,而v5会影响文件头,所以修改参数为:09CxxR@brUc3Exxx/1337test1/20testtest/=pizza/


QQ图片20240430152005.png (42.86 KB, 下载次数: 0)
下载附件
2024-5-2 00:45 上传

用010editor,可以看见test1开头就是0x11333377。继续sub_1400018B0函数,调试定位下一个exitprocess前面,看看需要什么条件。


QQ图片20240430152930.png (45.54 KB, 下载次数: 0)
下载附件
2024-5-2 00:43 上传



QQ图片20240430154109.png (121.96 KB, 下载次数: 0)
下载附件
2024-5-2 00:41 上传

调试可以得到,比较的是文件名,需要为pr.ost,  所以修改参数为09CxxR@brUc3Exxx/1337pr.ost/20testtest/=pizza/,成功通过判断。后面函数进入sub_140002170。
sub_140002170里面的逻辑是比较难以理解的,开头的sub_140001DA0,sub_140001F80返回的都是函数指针,然后里面的逻辑也是动态生成的,不能理解。sub_140001F80还受输入参数影响,会改变代码
试试用windbg从内存打印sub_140001DA0函数指针的汇编代码,进行分析,或者动态分析函数输入输出从而了解功能。sub_140001F80后面再分析。


QQ图片20240501171655.png (49.49 KB, 下载次数: 0)
下载附件
2024-5-2 00:35 上传



QQ图片20240501171239.png (60.98 KB, 下载次数: 0)
下载附件
2024-5-2 00:35 上传

sub_140001DA0的f1.bin丢进ninja可以反汇编为c语言,该函数功能与retrieve_140002F00一样,用'/'截取字符串,也可以通过动态分析根据输入输出知晓功能。


QQ图片20240430195325.png (78.34 KB, 下载次数: 0)
下载附件
2024-5-2 00:40 上传

shellcode2暂时理解不了,但他与shellcode3相关。但是我们可以猜想一下,输入的参数是个指针和字符串,输出是指针。那么就有这么几个情况,1.对字符串的处理,字符串对比或者添加什么的。2.看返回
值,shellcode2最后赋值给了*(a1+3C8),在后面的sub_140002910函数中,可以找到它被用做函数,所以返回的是函数指针,可以猜想shellcode2的作用可能是根据字符串查找函数地址,类似GetProcAddress
函数,shellcode2的输入指针还是shellcode3的返回值。理解shellcode2有助于理解shellcode3。先在shellcode3下断点,因为输入参数会影响shellcode3的代码,我们把汇编代码扣出来,慢慢分析。修改参数
为:09CxxR@brUc3Exxx/1337pr.ost/20testtest/=pizza/XXXXXXXXXXXXX/


QQ图片20240501125735.png (52.56 KB, 下载次数: 0)
下载附件
2024-5-2 00:39 上传



QQ图片20240501130330.png (43.85 KB, 下载次数: 0)
下载附件
2024-5-2 00:39 上传

将shellcode3抠出来的16进制,放到cyberchef,'X'的ASCII码是0x58,找到无效的指令,影响shellcode3代码的输入字符(第四段字符串),依次位置是“12,5,8,9,7,6”,然后仔细分析一下应该用什么代替


QQ图片20240501150354.png (98.25 KB, 下载次数: 0)
下载附件
2024-5-2 00:36 上传



QQ图片20240501153613.png (87.57 KB, 下载次数: 0)
下载附件
2024-5-2 00:35 上传

在上图,我们慢慢分析,首先第一个58 后面接着的是 “48 8b”,明显像mov指令,所以大概率是mov,那么什么指令后面还能接mov,而且"MOV RAX,QWORD PTR [0000000000000060]",有个60,显而易见[Asm] 纯文本查看 复制代码mov rax, qword ptr gs:[0x0000000000000060],该指令作用是通过peb获取模块地址,二进制如下:"\x65\x48\x8B\x04\x25\x60\x00\x00\x00\",其实知道了第一个指令的值,后面就很好知道了,显然shellcode3是通过peb获取指定模块地址,然后shellcode2从指定模块中获取指定函数地址。那么哪个模块有beep函数,谷歌搜一下我们知道Kernel32.dll(分析汇编代码也可知)。所以shellcode3是为了获取Kernel32.dll模块地址。
如果不熟悉,可以用搜索x64windows shellcode开发。后面的shellcode2修复也与之相关。修复后,汇编代码如下。


QQ图片20240501181210.png (71.02 KB, 下载次数: 0)
下载附件
2024-5-2 00:34 上传

Source[12] = 0x65 = e
Source[5]   = 0x60 = `
Source[8]   = 0x2e = .
Source[9]   = 0x43 = C
Source[7]   = 0x52 = R
Source[6]   = 0x30 = 0
MOV RAX,QWORD PTR GS:[0000000000000060] ;PEB基址
MOV RCX,QWORD PTR [RAX+18]  ;PEB中PEB_LDR_DATA 结构
; 获取 PEB_LDR_DATA 中的 InMemoryOrderModuleList 的地址
MOV RDX,QWORD PTR [RCX+20]
;获取LDR_DATA_TABLE_ENTRY 结构
SUB RDX,0000000000000010
; 判断模块名称
MOV RAX,QWORD PTR [RDX+60]
CMP WORD PTR [RAX+10],002E   ;'.'
JNE 000000000000004E
CMP WORD PTR [RAX+0E],0032   ;'2'
JNE 000000000000004E
CMP WORD PTR [RAX+0C],0033   ;'3'
JNE 000000000000004E
CMP WORD PTR [RAX+0A],004C   ;'L'
JE 000000000000003C
JS 0000000000000041
INS BYTE PTR [RDI],DX
JNE 000000000000004E
MOVZX EAX,WORD PTR [RAX+08]   ;'E'
MOV ECX,0000FFDF
SUB AX,0045   ;0x45='E'
TEST CX,AX
JE 0000000000000060
;循环 InMemoryOrderModuleList 的地址链表
MOV RAX,QWORD PTR [RDX+10]
;获取LDR_DATA_TABLE_ENTRY 结构
SUB RDX,0000000000000010
;判断DllBase是否为空
CMP QWORD PTR [RDX+30],0000000000000000
JNE 0000000000000015
XOR EAX,EAX
RET
;返回DllBase模块基址
MOV RAX,QWORD PTR [RDX+30]
RET
修改参数为:09CxxR@brUc3Exxx/1337pr.ost/20testtest/=pizza/XXXXX`0R.CXXeXXXX/。接着我们修复shellcode2,它也被输入参数影响。一样的,导入cyberchef,慢慢分析。


QQ图片20240501175352.png (68.48 KB, 下载次数: 0)
下载附件
2024-5-2 00:31 上传



QQ图片20240501175427.png (90.24 KB, 下载次数: 0)
下载附件
2024-5-2 00:31 上传

shellcode2功能与GetProcAddress一样,一顿操作猛如虎后,可以得到输入参数满足以下时,shellcode2可以运行。修改参数为:09CxxR@brUc3Exxx/1337pr.ost/20testtest/=pizza/AMu$E`0R.CAZeXXXX/
Source[1]   = 0x4d = M
Source[11] = 0x5a = Z
Source[4]   = 0x45 = E
Source[2]   = 0x75 = u
Source[3]   = 0x24 = $
Source[0]   = Source [10] = 0x41 = A
1.转到PE头(偏移量0x3c)
2.转到导出表(偏移量0x88)
3.转到名称表(偏移量0x20)
4.获取函数名称
5.比较名称
6.转到序数表(偏移量0x24)
7.获取功能号码
8.转到地址表(偏移量0x1c)
9.获取功能地址
MOV QWORD PTR [RSP+08],RBX
MOV QWORD PTR [RSP+18],RDI
MOV QWORD PTR [RSP+10],RDX ;'beep'
MOV R8,RCX
TEST RCX,RCX
JE 000000000000007A
MOV EAX,00005A4D   ;'ZM'   PE头
CMP WORD PTR [RCX],AX
JNE 000000000000007A
MOVSXD RAX,DWORD PTR [RCX+3C]
CMP DWORD PTR [RAX+RCX],00004550  ;'PE' magic
JNE 000000000000007A
MOV R9D,DWORD PTR [RAX+RCX+00000088]
ADD R9,RCX
MOV R11D,DWORD PTR [R9+20]
ADD R11,RCX
XOR ECX,ECX
CMP DWORD PTR [R9+18],ECX
JBE 000000000000007A
MOV EAX,DWORD PTR [R11+RCX*4]
MOV RBX,QWORD PTR [RSP+10]
ADD RAX,R8
SUB RBX,RAX
MOV EDI,ECX
MOVZX EDX,BYTE PTR [RAX]
MOVZX R10D,BYTE PTR [RAX+RBX]
SUB EDX,R10D
JNE 000000000000006E
INC RAX
TEST R10D,R10D
JNE 0000000000000059
TEST EDX,EDX
JE 0000000000000087
INC ECX
CMP ECX,DWORD PTR [R9+18]
JB 0000000000000048
XOR EAX,EAX
MOV RBX,QWORD PTR [RSP+08]
MOV RDI,QWORD PTR [RSP+18]
RET
MOV ECX,DWORD PTR [R9+24]
ADD RCX,R8
MOVZX EDX,WORD PTR [RCX+RDI*2]
MOV ECX,DWORD PTR [R9+1C]
ADD RCX,R8
MOV EAX,DWORD PTR [RCX+RDX*4]
ADD RAX,R8
JMP 000000000000007C
又完成一个套娃,继续下一个sub_140002910。又多了一段,在memcmp下断点,看看比较的啥


QQ图片20240501203625.png (37.91 KB, 下载次数: 0)
下载附件
2024-5-2 00:29 上传



QQ图片20240501204919.png (69.32 KB, 下载次数: 0)
下载附件
2024-5-2 00:29 上传

输入全是'X'  ,输出全是'E',  得与RUECKWAERTSINGENIEURWESEN相等,应该存在某种对应关系,将A~F作为输入看看,修改参数为:09CxxR@brUc3Exxx/1337pr.ost/20testtest/=pizza/AMu$E`0R.CAZeXXXX/ABCDEFGHIJKLMNOPQRSTUVWXYZ/


QQ图片20240501211143.png (72.65 KB, 下载次数: 0)
下载附件
2024-5-2 00:28 上传

所以ABCDEFGHIJKLMNOPQRSTUVWXYZ对应着VPWLCJSFTXKHINGUBYZDOMQERA,用py推一下,修改参数为:09CxxR@brUc3Exxx/1337pr.ost/20testtest/=pizza/AMu$E`0R.CAZeXXXX/YPXEKCZXYIGMNOXNMXPYCXGXN/
table = str.maketrans("VPWLCJSFTXKHINGUBYZDOMQERA", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
key = "RUECKWAERTSINGENIEURWESEN"
output = key.translate(table)
print(output) # YPXEKCZXYIGMNOXNMXPYCXGXN
继续程序运行到sub_140002670,又多了一段字符串。。修改参数为:09CxxR@brUc3Exxx/1337pr.ost/20testtest/=pizza/AMu$E`0R.CAZeXXXX/YPXEKCZXYIGMNOXNMXPYCXGXN/XXXXXXXXXXX/


QQ图片20240501221936.png (77.71 KB, 下载次数: 0)
下载附件
2024-5-2 16:17 上传

在0x26e1 有三个比较,动态调试,看看比较了什么。


QQ图片20240501215550.png (100.92 KB, 下载次数: 0)
下载附件
2024-5-2 00:27 上传



QQ图片20240501220835.png (55.73 KB, 下载次数: 0)
下载附件
2024-5-2 00:28 上传

0x6335626f转为字符就是'ob5c',改一下参数,继续调试下一个比较, 0x7255 对应 'Ur',其实它比较的就是第0段未使用的5个字符
[color=]'
brUc3'。
改参,调试下一个,只有一个33对应字符'3' , 修改参数:09CxxR@brUc3Exxx/1337pr.ost/20testtest/=pizza/AMu$E`0R.CAZeXXXX/YPXEKCZXYIGMNOXNMXPYCXGXN/ob5cUr3/


QQ图片20240502012024.png (75.62 KB, 下载次数: 0)
下载附件
2024-5-2 01:21 上传

[color=]如果之前'0x1f+day' 即字符'=' 那个地方没注意,偏移0x27ff会判断失败程序退出,当然一个字符我们也可以爆破。如果第0段的'
brUc3'不知道的话,就推不出ob5cUr3,那么byte_140049420就会解密错误的指令,影响后面指令的执行。运行到sub_140002670函数的最后,偏移0x290A,进入指令,看看干了啥,看到了call    qword ptr [rcx+390h],还有参数8,明显又套了一层娃,修改参数:09CxxR@brUc3E/1337pr.ost/20testtest/=pizza/AMu$E`0R.CAZe/YPXEKCZXYIGMNOXNMXPYCXGXN/ob5cUr3/XXXXXX/ ,将之前多余的X都去掉(影响程序运行)


QQ图片20240502014324.png (283.51 KB, 下载次数: 0)
下载附件
2024-5-2 01:45 上传



QQ图片20240502014332.png (133.14 KB, 下载次数: 0)
下载附件
2024-5-2 01:45 上传

调试一下就可以得到最后的答案了,最终参数为09CxxR@brUc3E/1337pr.ost/20testtest/=pizza/AMu$E`0R.CAZe/YPXEKCZXYIGMNOXNMXPYCXGXN/ob5cUr3/fin/


QQ图片20240502022914.png (282.2 KB, 下载次数: 0)
下载附件
2024-5-2 02:30 上传

总结
该程序通过命令行参数,控制文件的生成,并对文件进行修改,还会校验文件内容,并且通过参数控制shellcode的执行。
这才第三题,对于我这种小白,不敢想象后面是啥。。。
参考链接
writeup
官方solutions

下载次数, 下载附件

csl丶龙   

牛逼得很
Cleaf007   

硬核干货,学习一下
您需要登录后才可以回帖 登录 | 立即注册

返回顶部