攻防世界 reverse evil
这是2017 ddctf的一道逆向题,
挑战:《恶意软件分析》
赛题背景: 员工小A收到了一封邮件,带一个文档附件,小A随手打开了附件。随后IT部门发现小A的电脑发出了异常网络访问请求,进一步调查发现小A当时所打开的附件其实是一个伪装成word文档的恶意可执行文件。
赛题描述: 请在试着分析evil.exe和其所下载的x.jpg, 从中找出key.
评分标准: 密钥正确则可进入下一题。
攻防世界只给了exe文件,没有给x.jpg文件,(每个人的x.jpg文件是不同的,解得的flag也是不一样的。)
查壳: UPX(3.91)[NRV,best]
脱壳:
工具脱壳失败,手动脱壳。
两次esp脱壳法,dump。
(第一次脱没脱干净,但发现可以静态分析,0.0)
具体分析可参考:
【CTF习题】恶意软件分析
https://www.52pojie.cn/thread-679122-1-1.html
(出处: 吾爱破解论坛)
1 int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) 2 { 3 char *new_data; // ST10_4 4 int key[67]; // [esp+4h] [ebp-118h] 5 size_t dwSize; // [esp+114h] [ebp-8h] 6 void *jpg_data; // [esp+118h] [ebp-4h] 7 8 if ( sub_401370(hInstance) == 6 ) 9 return 0; 10 sub_401620(); 11 jpg_data = download_xjpg_4018F0(&dwSize); 12 if ( jpg_data ) 13 { 14 if ( dwSize ) 15 { 16 new_data = malloc(dwSize); 17 init_key_401740(key, 0x4A8754F5745174ui64); 18 decrypt_401800(key, jpg_data, new_data, dwSize); 19 exec_shellcode_401220(new_data, dwSize); 20 } 21 free(jpg_data); 22 } 23 return 0; 24 }
在decrypt_401800函数中,我把参数一定义成了个结构体,两个int型成员,一个byte[256]数组
00000000 key_struct struc ; (sizeof=0x108, mappedto_22) 00000000 x dd ? 00000004 y dd ? 00000008 key_data db 256 dup(?) 00000108 key_struct ends
这样再看清晰了一些
1 void __cdecl decrypt_401800(key_struct *key, char *jpg_data, char *new_data, unsigned int dwsize) 2 { 3 unsigned __int8 v4; // ST02_1 4 unsigned __int8 v5; // ST03_1 5 unsigned int i; // [esp+4h] [ebp-4h] 6 7 for ( i = 0; i < dwsize; ++i ) 8 { 9 key->x = (key->x + 1) % 256; 10 key->y = (key->key_data[key->x] + key->y) % 256; 11 v4 = key->key_data[key->x]; 12 v5 = key->key_data[key->y]; 13 key->key_data[key->x] = v5; 14 key->key_data[key->y] = v4; 15 new_data[i] = key->key_data[(v5 + v4) % 256] ^ jpg_data[i]; 16 } 17 }
wp:
1 key=[] 2 a=0x4A8754F5745174 3 temp=[0 for i in range(8)] 4 for i in range(8): 5 temp[i]=a 6 a=a>>8 7 for i in range(256): 8 key.append((i+temp[i%8])&0xff) 9 10 11 f=open('x.jpg','rb') 12 jpg_data=f.read() 13 new_data=[] 14 f.close() 15 x=0 16 y=0 17 for i in range(len(jpg_data)): 18 x=(x+1)%256 19 y=(key[x]+y)%256 20 key[x],key[y]=key[y],key[x] 21 new_data.append(((key[(key[x]+key[y])%256]^jpg_data[i])^i)&0xff) 22 # print(new_data) 23 mf=open('mydecrypt','wb') 24 mf.write(bytes(new_data)) 25 mf.close() 26 27 new_data=bytes(new_data) 28 flag = [] 29 i = 0 30 while(i<len(new_data)): 31 if(new_data[i]==0x68):#这里是解析push指令,保存压栈数据 32 flag.append(new_data[i+1:i+5]) 33 i += 3 34 i += 1 35 36 for i in flag[::-1]: #输出压栈数据 37 print(str(i)[2:-1], end='') 38 print()
输出:
Key: DDCTF-cc49badacb1c4d69bd4ae7173d9e9ade@didichuxing.comXCongratsX user32.dll A\x8eN\x0e\xec
这题做的话最简单的方法就是搭本地服务,然后动态调试,省时省力。
整体上程序流程清晰,算法还原也不复杂。
脱壳请参考:https://www.cnblogs.com/dliv3/p/6909066.html
攻防世界 key来源:https://blog.csdn.net/qq_38025365/article/details/89389311
DDCTF-01c981e4d5ea4da6b38b2990abbaf411@didichuxing.com
(滴滴的题还是蛮有趣的)