【CTF REVERSE】ctf02-查找字符串

1、前言

公司大拿给写的一个CTF逆向程序,提升我们组内人员的水平。

基于对话框MFC框架开发,使用EDIT控制特性隐藏Flag,可借助spy4win之类窗体工具找出Flag。
程序加UPX壳,已对壳信息混淆处理,PEiD无法识别出壳信息。
DLL 依赖情况如图所示。

2、思路

程序用IDA查看的时候,因为有壳混淆后是没法跟下去的。这道题比较简单,破解还是常规思路。。。

  • 1)手动脱UPX壳
  • 2)IDA查找字符串,获取信息
  • 3)跟踪调用的函数

3、过程

1、脱壳

UPX是一款常用的压缩壳,单步跟踪法或者是ESP定律都能很快的脱掉它。

单步跟踪到如下反汇编指令处:


00406A10 pushad
00406A11 mov esi,ctf02.00406000
00406A16 lea edi,dword ptr ds:[esi-0x5000]
00406A1C push edi
00406A1D or ebp,-0x1
00406A20 jmp short ctf02.00406A32

F8单步向下运行,遇到向上的跳转就F4到下一条指令去,不让自己迷失在各种解密操作指令中。

00406A32 mov ebx,dword ptr ds:[esi]
00406A34 sub esi,-0x4
00406A37 adc ebx,ebx
00406A39 jb short ctf02.00406A28 ; 向上跳转,跳转实现向上运行
00406A3B mov eax,0x1 ; F4运行到此处,遇到红色跳转就下一条
00406A40 add ebx,ebx
00406A42 jnz short ctf02.00406A4B
00406A44 mov ebx,dword ptr ds:[esi]
00406A46 sub esi,-0x4
00406A49 adc ebx,ebx
00406A4B adc eax,eax
00406A4D add ebx,ebx
00406A4F jnb short ctf02.00406A40
00406A51 jnz short ctf02.00406A5C
00406A53 mov ebx,dword ptr ds:[esi]
00406A55 sub esi,-0x4
00406A58 adc ebx,ebx
00406A5A jnb short ctf02.00406A40
00406A5C xor ecx,ecx
00406A5E sub eax,0x3
00406A61 jb short ctf02.00406A70
00406A63 shl eax,0x8
00406A66 mov al,byte ptr ds:[esi]
00406A68 inc esi ; ctf02.0040600B
00406A69 xor eax,-0x1
00406A6C je short ctf02.00406AE2
00406A6E mov ebp,eax
00406A70 add ebx,ebx

接下来会遇见两个向上的跳转,一个小跳转,一个大跳转。

我们在NOP指令的下一行代码F4运行到那一条,接下来的操作就比较重复化,遇到跳转就F4到下一条。

然后遇到popad指令的时候说明我们距离OEP就不远了!

00406ABD mov al,byte ptr ds:[edx]
00406ABF inc edx ;
00406AC0 mov byte ptr ds:[edi],al
00406AC2 inc edi ;
00406AC3 dec ecx
00406AC4 jnz short ctf02.00406ABD ; 小跳转
00406AC6 jmp ctf02.00406A2E ; 大跳转
00406ACB nop
00406ACC mov eax,dword ptr ds:[edx] ; F4运行到此处
00406ACE add edx,0x4
00406AD1 mov dword ptr ds:[edi],eax
00406AD3 add edi,0x4
00406AD6 sub ecx,0x4
00406AD9 ja short ctf02.00406ACC ; 又是一个跳转的地方
00406ADB add edi,ecx ; F4运行到此处
00406ADD jmp ctf02.00406A2E ; 大跳转,F4运行到下一条语句
00406AE2 pop esi ;
00406AE3 mov edi,esi ; F4运行到此处
00406AE5 mov ecx,0x3B
00406AEA mov al,byte ptr ds:[edi]
00406AEC inc edi ;
00406AED sub al,0xE8
00406AEF cmp al,0x1
00406AF1 ja short ctf02.00406AEA ; 小跳转
00406AF3 cmp byte ptr ds:[edi],0x1 ; F4运行到此处
00406AF6 jnz short ctf02.00406AEA
00406AF8 mov eax,dword ptr ds:[edi] ; F4运行到此处
00406AFA mov bl,byte ptr ds:[edi+0x4]
00406AFD shr ax,0x8
00406B01 rol eax,0x10
00406B04 xchg ah,al
00406B06 sub eax,edi ;
00406B08 sub bl,0xE8
00406B0B add eax,esi ;
00406B0D mov dword ptr ds:[edi],eax
00406B0F add edi,0x5
00406B12 mov al,bl
00406B14 loopd short ctf02.00406AEF ; 循环操作
00406B16 lea edi,dword ptr ds:[esi+0x4000] ; F4运行到此处
00406B1C mov eax,dword ptr ds:[edi]
00406B1E or eax,eax
00406B20 je short ctf02.00406B67
00406B22 mov ebx,dword ptr ds:[edi+0x4]
00406B25>lea eax,dword ptr ds:[eax+esi+0x68BC]
00406B2C add ebx,esi ;
00406B2E push eax
00406B2F add edi,0x8
00406B32 call dword ptr ds:[esi+0x6920] ;
00406B38 xchg eax,ebp ;
00406B39 mov al,byte ptr ds:[edi]
00406B3B inc edi ;
00406B3C or al,al
00406B3E je short ctf02.00406B1C
00406B40 mov ecx,edi ;
00406B42 jns short ctf02.00406B4B
00406B44 movzx eax,word ptr ds:[edi]
00406B47 inc edi ;
00406B48 push eax
00406B49 inc edi ;
00406B4A db B9
00406B4B push edi ;
00406B4C dec eax
00406B4D repne scas byte ptr es:[edi]
00406B4F push ebp ;
00406B50 call dword ptr ds:[esi+0x6924] ;
00406B56 or eax,eax
00406B58 je short ctf02.00406B61
00406B5A mov dword ptr ds:[ebx],eax
00406B5C add ebx,0x4
00406B5F jmp short ctf02.00406B39 ; 无条件跳转
00406B61 call dword ptr ds:[esi+0x6934] ;
00406B67 mov ebp,dword ptr ds:[esi+0x6928] ; F4运行到此处
00406B6D lea edi,dword ptr ds:[esi-0x1000]
00406B73 mov ebx,0x1000
00406B78 push eax
00406B79 push esp
00406B7A push 0x4
00406B7C push ebx
00406B7D push edi ;
00406B7E call ebp ;
00406B80 lea eax,dword ptr ds:[edi+0x207]
00406B86 and byte ptr ds:[eax],0x7F
00406B89 and byte ptr ds:[eax+0x28],0x7F
00406B8D pop eax
00406B8E push eax
00406B8F push esp
00406B90 push eax
00406B91 push ebx
00406B92 push edi ;
00406B93 call ebp ;
00406B95 pop eax
00406B96 popad ; 到这里的时候说明快到OEP了
00406B97 lea eax,dword ptr ss:[esp-0x80]
00406B9B push 0x0
00406B9D cmp esp,eax
00406B9F jnz short ctf02.00406B9B
00406BA1 sub esp,-0x80
00406BA4 jmp ctf02.00401750 ; 跳转到OEP

到了00406BA4 这里的时候,我用OD插件-Ollydump脱壳。

【CTF REVERSE】ctf02-查找字符串

2、IDA查看

脱了壳后的程序,用IDA看就没有障碍了。

IDA打开后-View - Open Subviews - Srings

【CTF REVERSE】ctf02-查找字符串

然后X键,查看哪个函数在引用它,F5查看C源码就确认出Flag了。

signed int __thiscall sub_4012B0(CDialog *this)
{
CDialog *v1; // esi@1
HMENU v2; // eax@1
struct CMenu *v3; // edi@1
LPCSTR lpNewItem; // [sp+8h] [bp-10h]@2
int v6; // [sp+14h] [bp-4h]@2 v1 = this;
CDialog::OnInitDialog(this);
v2 = GetSystemMenu(*((HWND *)v1 + 8), 0);
v3 = CMenu::FromHandle(v2);
if ( v3 )
{
CString::CString(&lpNewItem);
v6 = 0;
CString::LoadStringA((CString *)&lpNewItem, 0x65u);
if ( *((_DWORD *)lpNewItem - 2) )
{
AppendMenuA(*((HMENU *)v3 + 1), 0x800u, 0, 0);
AppendMenuA(*((HMENU *)v3 + 1), 0, 0x10u, lpNewItem);
}
v6 = -1;
CString::~CString((CString *)&lpNewItem);
}
SendMessageA(*((HWND *)v1 + 8), 0x80u, 1u, *((_DWORD *)v1 + 40));
SendMessageA(*((HWND *)v1 + 8), 0x80u, 0, *((_DWORD *)v1 + 40)); //发送消息到窗口
CWnd::SetWindowTextA((CDialog *)((char *)v1 + 96), "6C9F69EF-C170-4e43-A007-9AA3526823DB"); //设置文本
SendMessageA(*((HWND *)v1 + 32), 0xCCu, 0x2Eu, 0);
return 1;
}

4、附件下载地址

https://github.com/zprogram/zprogram.github.io/blob/master/Blog_attachment/CTF/CTF_REVERSE_ctf02_查找字符串.zip

5、参考

手脱UPX壳的几种方法

http://blog.csdn.net/xiaoyuai1234/article/details/51463501

上一篇:Linux下如何查看高CPU占用率线程


下一篇:Linux下如何查看高CPU占用率线程 LINUX CPU利用率计算