-
-
[原创]看雪CTF 2019Q3 第二题 血肉佣兵
-
2019-9-21 15:15 3310
-
这是作者第三次改版的题目,上一次是个微型的vm,但这一次没看出来是什么
与Q1赛季题目的异同
同
- 在
00498C00 _Tfrmcrackme_FormCreate
事件函数的00498C72 call sub_4969C0
函数中注册sptWBCallback
回调函数,回调函数地址:00496C7C
- 加载
HTML
作为界面,JavaScript
获取输入,触发sptWBCallback
事件function ckpswd() { key = "simpower91"; a = document.all.pswd.value; if (a.indexOf(key) == 0) { l = a.length; i = key.length; sptWBCallback(a.substring(i, l)); } else { alert("wrong!<" + a + "> is not my GUID ;-)"); return "1234"; } } function ok() { alert("congratulations!"); }
异
1. js代码没有触发sptWBCallback
回调
将
simpower91
放在输入的开头,并不能触发sptWBCallback
回调函数
- 原因是在
_Tfrmcrackme_FormCreate
事件函数中又注册了一个定时事件,修改了内存中加载的js代码CODE:00498D1B push ebx CODE:00498D1C push offset sub_499388 ; 替换 simpower91 首字母为大写 CODE:00498D21 mov eax, [ebx+33Ch] ; this CODE:00498D27 call @Idsyslogmessage@TIdSysLogMessage@SetTimeStamp$qqrx16System@TDateTime // 定时事件函数替换代码 sub_499388: CODE:004993B5 mov eax, [ebp+System::AnsiString] ; System::AnsiString CODE:004993B8 mov ecx, offset _str_d_return_Si.Text ; int CODE:004993BD mov edx, offset _str_d_return_si.Text ; System::AnsiString CODE:004993C2 call SysUtils_StringReplace
- 所以实际内存中加载的js验证代码如下
function ckpswd() { key = "Simpower91"; a = document.all.pswd.value; if (a.indexOf(key) == 0) { l = a.length; i = key.length; sptWBCallback(a.substring(i, l)); } ......
2.sptWBCallback
回调函数中的验证代码与之前不同(解题过程)
00496E08 call dword ptr [ebx+40h]
该位置调用反调试函数- 之后的
call
指令在F8
单步的时候,程序会重新跑起来,于是依次F8 F7
确认后来到了如下位置... 004772CE -> 00476C3E -> 00475C64 -> 00474EF5 -> 00474EA2 -> 00474E98
CODE:00474E98 f_call_fun_474E98 proc near ; CODE XREF: sub_474EAC+49↓p CODE:00474E98 CODE:00474E98 arg_0 = dword ptr 8 CODE:00474E98 arg_4 = dword ptr 0Ch CODE:00474E98 arg_8 = dword ptr 10h CODE:00474E98 CODE:00474E98 push ebp ; SimInstructions.sub_00474E98 CODE:00474E99 mov ebp, esp CODE:00474E9B mov eax, [ebp+arg_0] CODE:00474E9E push eax CODE:00474E9F mov eax, [ebp+arg_8] CODE:00474EA2 call [ebp+arg_4] CODE:00474EA5 pop ebp CODE:00474EA6 retn 0Ch CODE:00474EA6 f_call_fun_474E98 endp
- 可以看出这个函数
00474EA2
的位置会调用参数中传进来的函数,最后跑飞的位置也在这里,疑似某种事件函数 - 输入
Simpower910123
在这里下断点持续观察,会发现输入的字符串地址会在其中一次命中断点时出现在寄存器窗口 - 这里调用的函数是
sub_471720
,调试后会发现此时将传进来的字符串的第一个字符作为DWORD
数据保存在了函数第4个参数指向的地址中 - 因为后面还有很多函数调用,不确定哪个函数是关键,于是在保存后的
DWORD
数据那里下硬件访问断点,再确认是否为验证操作 - 经过两次断点触发,来到这里
00470A21
,发现给第一个字符加上了7F
,最后保存在了原位置 - 再经过几次断点触发,来到这里
00470B36
(注意在这里下个断点),发现将加上7F
的数据再次减E0
,将结果保存在edx
中 - 然后
F7
单步,一直到这里,发现有个比较edx
值是不是0
的操作,于是怀疑这里就是判断,手动将edx
的值改为0
- 然后删除之前给数据下的硬件断点,
F9
运行观察一下,经过几次断点触发,又来到这这个熟悉的地方,不一样的是,开始操作第二个字符了 - 于是重复刚才的操作会发现
str[0] + 7F == E0 str[1] + 7F == B2 str[2] + 7F == B1 str[3] + 7F == B0
- 算出输入的值:
E0 - 7F = 61 B2 - 7F = 33 B1 - 7F = 32 B0 - 7F = 31 // a123
答案
Simpower91a321 // 这个答案。。。上次是a123,这次是a321,这说不定那个大佬猜都猜对了
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界
赞赏
他的文章
谁下载
无
看原图