170925 逆向-Reversing.kr(Replace)
来源:互联网 发布:使用js完成九九乘法表 编辑:程序博客网 时间:2024/06/16 21:41
1625-5 王子昂 总结《2017年9月25日》 【连续第358天总结】
A. Reversing.kr-Replace
B.
Replace
先查一波壳,还好没有
运行,是一个GUI程序,下面Label框中显示Wrong!,说明没法找Msgbox了呢
随便输入后点Check,就停止运行了……嗯?这么暴力的,输错就GG吗
惯例拖入IDA,WinMain中只有构造窗口的DialogBoxParamA函数,回调函数使用了DialogFunc
搜索字符串发现Correct!在DialogFunc中有引用,遂查看代码并反编译:
// write access to const memory has been detected, the output may be wrong!BOOL __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4){ BOOL result; // eax@2 if ( a2 == 273 ) { if ( (unsigned __int16)a3 == 2 ) { EndDialog(hDlg, 2); result = 1; } else if ( (unsigned __int16)a3 == 1003 ) { input = GetDlgItemInt(hDlg, 1002, 0, 0); sub_40466F(); ((void (__cdecl *)(void *))loc_404689)(&loc_40469F); *(_DWORD *)sub_40466F = -1013972794; sub_40466F(); sub_40466F(); *(_DWORD *)sub_40466F = 1768; result = 1; } else { result = 0; } } else { result = 0; } return result;}
查了一波API手册,发现回调函数其实叫DialogProc,参数说明只能知道a2为指定消息uMsg,a3为指定消息的其他信息wParam
想研究一波前面判断的具体信息,但是没找到相关手册说明uMsg的对应表
内层循环体的GetDlgItemInt很明显就是获取对话框的值
输入了一下试试,发现只能接受数字,字母和符号都是无法输入的
在OD中下断DialogFunc,发现窗口开启状态下会不停地断到,说明消息是不断传送的。似乎是当焦点在窗口上方时a2=273,点击按钮时a3=3。
参数不搞明白倒是不怎么影响啦,在内层循环体下断可以在点击按钮后断到
将输入送入0x4084d0后就call 0040466F了
这个call是一个很关键很有趣的点,需要慢慢地仔细分析
首先回忆一下汇编中函数调用的相关知识
当call某处时,首先将下一条指令的地址压入栈中,然后将EIP改至该行
即相当于
push eip+x ;x是本次指令的长度
jmp n ;n是函数地址
函数运行完以后执行retn,将栈中之前的地址pop出栈,送入EIP中,继续运行
即相当于
pop eip
下面分析代码
0040466F $ E8 06000000 call Replace.0040467A00404674 81 db 8100404675 . 05 D0844000 add eax,Replace.004084D00040467A . C705 16604000>mov dword ptr ds:[0x406016],0x619060EB00404684 . E8 00000000 call Replace.0040468900404689 /$ FF05 D0844000 inc dword ptr ds:[0x4084D0]0040468F \. C3 retn00404690 > A1 D0844000 mov eax,dword ptr ds:[0x4084D0]00404695 . 68 9F464000 push Replace.0040469F0040469A . E8 EAFFFFFF call Replace.004046890040469F . C705 6F464000>mov dword ptr ds:[0x40466F],0xC39000C6004046A9 . E8 C1FFFFFF call Replace.0040466F004046AE . 40 inc eax004046AF . E8 BBFFFFFF call Replace.0040466F004046B4 . C705 6F464000>mov dword ptr ds:[0x40466F],0x6E8004046BE . 58 pop eax ; Replace.00401020004046BF . B8 FFFFFFFF mov eax,-0x1004046C4 .^ E9 A8C9FFFF jmp Replace.00401071
进去就call 40467A
为另外一处赋值以后继续call 404689
在这里为我们的输入+1,然后ret n,即回到刚才call的下一行:404689
于是输入再+1,然后ret n,即回到最外层call的下一行:404674
关键来了,404674是db 81,即未被分析的数字
这里单步执行会发现直接跳到了40467E
也就是说,这一次执行复用了本来的404675处的指令
从机器码可以看出指令内容应该是81 05 D0 84 40 00 C7 05 16 60
于是我就去百度了好久的机器码跟汇编对应指令,也没研究明白……
最后乖乖用自动工具了囧
后面其余的指令没什么意义,再往后执行又同样call了404689,对4084D0+2
即整个call对地址4084D0增加了4+0x601605C7
出来后jmp到了404690
00404690 > \A1 D0844000 mov eax,dword ptr ds:[0x4084D0]00404695 . 68 9F464000 push Replace.0040469F0040469A . E8 EAFFFFFF call Replace.004046890040469F . C705 6F464000>mov dword ptr ds:[0x40466F],0xC39000C6004046A9 . E8 C1FFFFFF call Replace.0040466F004046AE . 40 inc eax004046AF . E8 BBFFFFFF call Replace.0040466F004046B4 . C705 6F464000>mov dword ptr ds:[0x40466F],0x6E8004046BE . 58 pop eax ; Replace.00401020004046BF . B8 FFFFFFFF mov eax,-0x1004046C4 .^ E9 A8C9FFFF jmp Replace.00401071
这里把值先送到了eax里
然后push 40469F,这个是为了之后retn准备的,倒是不用在意
call 404689又为4084D0加了一
然后为40466F赋值,再call 40466F
很明显这个call是刚赋值过即更改了指令的,我们跟随过去看一眼:
0040466F $ C600 90 mov byte ptr ds:[eax],0x9000404672 ? C3 retn
对eax指向的内容赋值90
这里很明显就是之前随手输入报错的原因了:eax指向的地址不合法
我们修改一下eax使得它可以继续运行,找一个隔壁空的地址写入eax就可以了
之后程序对eax+1,再次call 40466F。也就是说一次对两个字节的内存写入90
pwn做多了马上就能反应过来\x90是NOP的机器码,也就是说这个call可以抹消两个字节的指令
暂时不知道用处在哪里,我们继续往下运行
还原40466F后jmp 401071:
00401071 /EB 11 jmp short Replace.0040108400401073 |68 34604000 push Replace.00406034 ; Correct!00401078 |68 E9030000 push 0x3E9 ; |ControlID = 3E9 (1001.)0040107D . |56 push esi ; |hWnd = 004000D00040107E . |FF15 A0504000 call dword ptr ds:[<&USER32.SetDlgItemTe>; \SetDlgItemTextA00401084 > \B8 01000000 mov eax,0x100401089 . 90 nop0040108A . 90 nop0040108B . 90 nop0040108C . 90 nop0040108D . 90 nop0040108E . 90 nop0040108F . 90 nop00401090 . 5E pop esi ; Replace.004000D000401091 . 5D pop ebp00401092 . C2 1000 retn 0x10
我们可以看到,Correct的显示是通过SetDlgItemTextA的,现在执行近在咫尺,却又有一个jmp跳过了它。
并且注意OD显示,这个API前方到jmp之间是没有跳转落点的
也就是说,正常执行情况下,最多跳到401071,然后jmp走
那么很明显,要显示Correct,我们就要爆破掉这个jmp
而程序正好自己提供了两个字节的NOP来爆破
也就是说我们只需要计算好地址,使得call 40466F正好抹掉这个jmp就行了
它的地址是00401071,中间的计算是加0x601605CB(注意虽然最后有一个对内存的+1,但是40466F的操作数是eax,所以最终仍然是+4)
加数比得数大,因此需要利用eax的溢出
正好win10的计算器方便的不行,提供了程序员模块,将类型改至DWORD,就得到了结果:
注意输入的是十进制DEC,并且去掉负号哦~
C. 明日计划
Reversing.kr
- 170925 逆向-Reversing.kr(Replace)
- 【reversing.kr】Replace逆向分析
- 【Reversing.kr】Replace.exe
- 170923 逆向-Reversing.kr(MusicPlayer)
- 170926 逆向-Reversing.kr(ImagePrc)
- 170927 逆向-Reversing.kr(Position)
- 170928 逆向-Reversing.kr(Direct3D_FPS)
- 170929 逆向-Reversing.kr(Ransomware)
- 170930 逆向-Reversing.kr(Twist)
- 171001 逆向-Reversing.kr(WindowsKernel)
- 171002 逆向-Reversing.kr(AutoHotKey)
- 171003 逆向-Reversing.kr(CSHOP)
- 171010 逆向-Reversing.kr(PEPassword)
- 171011 逆向-Reversing.kr(HateIntel)
- 171013 逆向-Reversing.kr(AutoHotKey2)
- 171014 逆向-Reversing.kr(x64 Lotto)
- 171017 逆向-Reversing.kr(CSharp)
- 171018 逆向-Reversing.kr(Flash Encrypt)
- 2017/9/25工作总结
- 深入浅出Node.js之CommonJS的模块规范
- Android键值添加和调试
- LeetCode49_Group Anagrams
- MT n91 Request for Payment of Charges, Interest and Other Expenses收费、利息和其他费用支付请求
- 170925 逆向-Reversing.kr(Replace)
- Java基础知识---内存区域与内存溢出异常
- 印度比中国可怕在哪里?一能力或成超越中国的秘密武器
- 有点坑的unity协程
- Java中的BIO、NIO、AIO(NIO2)
- React+webpack+Less 组件样式覆盖优化
- 周末总结
- MT 192 Request for Cancellation撤销请求
- 挑战题一(2)