首页
社区
课程
招聘
[原创]第一题:无限流[签到题] Writeup
发表于: 2019-12-2 17:31 2363

[原创]第一题:无限流[签到题] Writeup

2019-12-2 17:31
2363
1
title: 看雪CFT第一题writeup date: 2019-12-02 15:53:59 tags: - ctf


IDA 版本: 6.8

题目连接:https://ctf.pediy.com/game-season_fight-125.htm

跟着思路写的。。。。有点乱,千万分析汇成最后一段python代码

输入成功失败



拖入IDA 中,搜索关键词

这段是输入错误时的提示,右键rename成,方便查看


他上面这段就是成功的提示,成success

找到调用他的地方,发现是通过strcmp字符串对比,对比成功就显示成功,失败就显示失败


应该就是将输入的和str2 ()对比,对比成功就成功

1
检查结果段的代码<br>​<br>.text:004017F0 ; int __cdecl checkresult(char *Str1)<br>.text:004017F0 checkresult     proc near               ; CODE XREF: sub_401830+D7•p<br>.text:004017F0<br>.text:004017F0 Str1            = dword ptr  8<br>.text:004017F0<br>下面这三步是在一起的似乎。。。<br>.text:004017F0                 push    ebp<br>.text:004017F1                 mov     ebp, esp        ; 两个寄存器ebp,esp都保存上个函数的ebp值<br>.text:004017F3                 sub     esp, 40h<br>​<br>.text:004017F6                 push    ebx<br>.text:004017F7                 push    esi<br>.text:004017F8                 push    edi<br>.text:004017F9                 push    offset Str2     ; "goluck!"<br>.text:004017FE                 mov     eax, [ebp+Str1]<br>.text:00401801                 push    eax             ; Str1 eax 是Str1,就是第二个参数 <br>.text:00401802                 call    strcmp   ;调用字符串比较函数,前面是将参数压入栈<br>.text:00401807                 add     esp, 8   ;??<br>.text:0040180A                 test    eax, eax   ;检查eax是不是0,检查的结果设置到zf标记位<br>.text:0040180C                 jnz     short loc_401815 ; 如果zf不等于0,就跳到失败这里<br>.text:0040180E                 call    success<br>.text:00401813                 jmp     short loc_40181A<br>​<br>if(strcmp(str1,str2)!=0)<br>{<br>error()<br>}<br>else<br>success<br>​<br>str2是固定的,str1是输入的,但是直接将goluck!输入进去是不行的,说明是输入的正确答案,经过某种处理就变成goluck!,说明上面有个过程是<br>输入->str1<br>点击 CODE XREF: sub_401830+D7•p 跳到引用的地方

定位到这里,应该是上面有个循环


检查转换的完整代码

判断字符串长度是不是0,0的话直接显示失败

循环输入的字符串 3

1
​<br>.text:00401830 ; Attributes: bp-based frame<br>.text:00401830<br>.text:00401830 sub_401830      proc near               ; DATA XREF: .rdata:00403548•o<br>.text:00401830<br>.text:00401830 Str1            = byte ptr -18h<br>.text:00401830 var_10          = dword ptr -10h<br>.text:00401830 var_C           = dword ptr -0Ch<br>.text:00401830 Str             = dword ptr -8<br>.text:00401830 var_4           = dword ptr -4<br>.text:00401830<br>.text:00401830                 push    ebp<br>.text:00401831                 mov     ebp, esp<br>.text:00401833                 sub     esp, 58h<br>.text:00401836                 push    ebx<br>.text:00401837                 push    esi<br>.text:00401838                 push    edi<br>.text:00401839                 mov     [ebp+var_4], ecx<br>.text:0040183C                 mov     eax, [ebp+var_4]<br>.text:0040183F                 add     eax, 64h<br>.text:00401842                 push    eax             ; struct CString *<br>.text:00401843                 push    3EAh            ; int<br>.text:00401848                 mov     ecx, [ebp+var_4] ; this<br>.text:0040184B                 call    ?GetDlgItem@CWnd@@QBEPAV1@H@Z ; CWnd::GetDlgItem(int)<br>.text:00401850                 mov     ecx, eax        ; this<br>.text:00401852                 call    ?GetWindowTextA@CWnd@@QBEXAAVCString@@@Z ; CWnd::GetWindowTextA(CString &)<br>.text:00401857                 mov     ecx, [ebp+var_4]<br>.text:0040185A                 add     ecx, 64h<br>.text:0040185D                 call    sub_401970<br>.text:00401862                 push    eax             ; int<br>.text:00401863                 mov     ecx, [ebp+var_4]<br>.text:00401866                 add     ecx, 64h        ; this<br>.text:00401869                 call    ?GetBuffer@CString@@QAEPADH@Z ; CString::GetBuffer(int)<br>.text:0040186E                 mov     [ebp+Str], eax<br>.text:00401871                 mov     ecx, [ebp+Str]<br>.text:00401874                 push    ecx             ; Str<br>.text:00401875                 call    strlen          ; 判断字符串长度是不是0,是0就提示输入<br>.text:0040187A                 add     esp, 4<br>.text:0040187D                 test    eax, eax<br>.text:0040187F                 jnz     short loc_401894<br>.text:00401881                 push    0               ; unsigned int<br>.text:00401883                 push    0               ; char *<br>.text:00401885                 push    offset aIFIpassword ; "请输入password!"<br>.text:0040188A                 mov     ecx, [ebp+var_4] ; this<br>.text:0040188D                 call    ?MessageBoxA@CWnd@@QAEHPBD0I@Z ; CWnd::MessageBoxA(char const *,char const *,uint)<br>.text:00401892                 jmp     short loc_40190F<br>.text:00401894 ; ---------------------------------------------------------------------------<br>.text:00401894<br>.text:00401894 loc_401894:                             ; CODE XREF: sub_401830+4F•j<br>.text:00401894                 mov     [ebp+var_C], offset aCukOgl ; "cuk!ogl"<br>.text:0040189B                 mov     [ebp+var_10], 0<br>.text:004018A2                 mov     [ebp+var_10], 0<br>.text:004018A9<br>-------------------循环开始<br>根据输入的值计算 成str1<br>.text:004018A9 loc_4018A9:                             ; CODE XREF: sub_401830+C9•j<br>.text:004018A9                 mov     edx, [ebp+Str]  ; edx指向str(输入的字符串) <br>.text:004018AC                 add     edx, [ebp+var_10] ; var_10 作为数组索引<br>.text:004018AF                 movsx   eax, byte ptr [edx] ; 取出第var_10个元素放在eax里<br>.text:004018B2                 test    eax, eax        ; 看eax是不是0?<br>.text:004018B4                 jz      short loc_4018FB ; 表示没取到?跳出循环<br>​<br>​<br>检查当前遍历的字符串在不在'0''9'之间,就是说答案最后只能是数字<br>​<br>.text:004018B6                 mov     ecx, [ebp+Str] ecx = str1<br>.text:004018B9                 add     ecx, [ebp+var_10] <br>.text:004018BC                 movsx   edx, byte ptr [ecx]<br>.text:004018BF                 cmp     edx, 39h 0x39对应的是'1'这个字符串<br>.text:004018C2                 jg      short loc_4018EB ; 大于57就显示失败<br>.text:004018C4                 mov     eax, [ebp+Str]  ; eax=ebp+STR<br>.text:004018C7                 add     eax, [ebp+var_10]<br>.text:004018CA                 movsx   ecx, byte ptr [eax] ; 再取出来对比<br>.text:004018CD                 cmp     ecx, 30h        ; 小于48也错误<br>.text:004018D0                 jl      short loc_4018EB<br>​<br>根据输入的值 转换<br>.text:004018D2                 mov     edx, [ebp+Str]  ; 可能是设置数据到str1<br>.text:004018D5                 add     edx, [ebp+var_10]<br>.text:004018D8                 movsx   eax, byte ptr [edx] ; eax=data[i]<br>.text:004018DB                 mov     ecx, [ebp+var_10]<br>.text:004018DE                 mov     edx, [ebp+var_C] ; <br>al就是str1 的某个索引下的值 <br>​<br>a1 = edx_eax-0x30<br>edx 是上面var_c 是上面 [ebp+var_C], offset aCukOgl ; "cuk!ogl"<br>就是edx是这个字符串<br>edx[offset],offset就输入的ascii码-0x30<br>​<br>假设输入是input<br>str1[index]=aCukOgl[input[index]-30h]<br>​<br>最后的str1要是goluck!<br>然后每个倒过来计算一下就行<br>比如第一个index=0时<br>'g'=aCukOgl[input[index]-30h]<br>g在aCukOgl里的index是5<br>input[index]-0x30=5<br>input[index]=0x30+5=53='5'<br>​<br>​<br>​<br>​<br>​<br>​<br>.text:004018E1                 mov     al, [edx+eax-30h] ; a1l=edx+eax-30h<br>ecx上面设置成了var_10的值,就是 当前数组的索引, str[var_10]=al<br>.text:004018E5                 mov     [ebp+ecx+Str1], al<br>.text:004018E9                 jmp     short loc_4018F0<br>.text:004018EB ; ---------------------------------------------------------------------------<br>.text:004018EB<br>.text:004018EB loc_4018EB:                             ; CODE XREF: sub_401830+92•j<br>.text:004018EB                                         ; sub_401830+A0•j<br>.text:004018EB                 call    error<br>.text:004018F0<br>.text:004018F0 loc_4018F0:                             ; CODE XREF: sub_401830+B9•j<br>.text:004018F0                 mov     ecx, [ebp+var_10]<br>.text:004018F3                 add     ecx, 1<br>.text:004018F6                 mov     [ebp+var_10], ecx<br>.text:004018F9                 jmp     short loc_4018A9<br>.text:004018FB ; ---------------------------------------------------------------------------<br>.text:004018FB<br>.text:004018FB loc_4018FB:                             ; CODE XREF: sub_401830+84•j<br>.text:004018FB                 mov     edx, [ebp+var_10]<br>.text:004018FE                 mov     [ebp+edx+Str1], 0<br>.text:00401903                 lea     eax, [ebp+Str1]<br>.text:00401906                 push    eax             ; Str1<br>.text:00401907                 call    checkresult<br>.text:0040190C                 add     esp, 4<br>.text:0040190F<br>.text:0040190F loc_40190F:                             ; CODE XREF: sub_401830+62•j<br>.text:0040190F                 pop     edi<br>.text:00401910                 pop     esi<br>.text:00401911                 pop     ebx<br>.text:00401912                 mov     esp, ebp<br>.text:00401914                 pop     ebp<br>.text:00401915                 retn<br>.text:00401915 sub_401830      endp

根据上面的算法,得到的解题脚本


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册