2015_XDCTF_Reverse200_Writeup

OD加载程序,F9运行,提示输入flag。随便输入一个字符串,提示“you shall not pass!”

这道题是输入验证类型,验证的字符串是固定的,因此相对容易分析。验证可分为6个阶段:

① 验证长度

② 验证前6个字符

③ 验证第24位、第13位、第19位

④ 验证7~12位

⑤ 验证14~18位

⑥ 验证20~23位

具体分析步骤如下:

1.验证长度

重新加载,右键“查找”->"所有参考文本字串"。显示字符串(图 2.1), 发现很多“you shall not pass”,在汇编中从“you shall not pass ”往回找跳转句,在附近的比较函数(cmp)或test下断,F9运行,提示输入时输入一个字符串“12345”,回车,程序断在004011EB处,此句将堆栈 ss:[0012FE60]的内容和0x19(25)进行比较,大于等于跳转到提示错误,为零也提示错误。数据窗口中查看[0012FE60] 内存(图2.3),很明显此内存+8的地方存放了我们输入的flag,那这个内存存放的是什么呢?数据窗口中此处的值为5,可以联想到是输入flag的长度,可以调试前面的代码得证,换几个不同长度字符串输入也可以验证这一点。

往前可以找到“Give me the flag:”后面可以验证。F8单步,后面的jz和jnz都跳到了00401224,说明此段放行了长度满足0<n<25的输入字符串。

图 2.1

图 2.2

图 2.3

图 2.4

2.验证前6个字符

F8继续单步运行,下面的代码将输入的前6个字符和“XDCTF{”比较,相等则跳到0040130F处。(代码2.1)

;代码2.1004012AC    8B8D D0FEFFFF   mov ecx,dword ptr ss:[ebp-0x130]
004012B2    83C1 01         add ecx,0x1
004012B5    898D D0FEFFFF   mov dword ptr ss:[ebp-0x130],ecx
004012BB    8B95 E0FEFFFF   mov edx,dword ptr ss:[ebp-0x120]
004012C1    83EA 01         sub edx,0x1
004012C4    3995 D0FEFFFF   cmp dword ptr ss:[ebp-0x130],edx ;  控制比较次数为6次
004012CA    7F 3C           jg Xctf2.00401308
004012CC    8B85 D0FEFFFF   mov eax,dword ptr ss:[ebp-0x130]
004012D2    0FBE8C05 70FFFF>movsx ecx,byte ptr ss:[ebp+eax-0x90]
004012DA    8B95 D0FEFFFF   mov edx,dword ptr ss:[ebp-0x130]
004012E0    0FBE8415 F0FEFF>movsx eax,byte ptr ss:[ebp+edx-0x110]
004012E8    3BC8            cmp ecx,eax         ;将输入的前六个字符和”XDCTF_”比较
004012EA    74 1A           je Xctf2.00401306
004012EC    68 7CCA4000     push ctf2.0040CA7C                       ; ASCII "You shall not pass!"
004012F1    E8 0B070000     call ctf2.00401A01
004012F6    83C4 04         add esp,0x4
004012F9    E8 CD070000     call ctf2.00401ACB
004012FE    83C8 FF         or eax,0xFFFFFFFF
00401301    E9 72030000     jmp ctf2.00401678
00401306  ^ EB A4           jmp Xctf2.004012AC

3.验证第24位、第13位、第19位

分析到这里我们不妨换一个字符串输入,就取它最大允许的长度24,输入“XDCTF{123456789ABCDEFGH}”,果然程序跳到0040130F处(代码3.1)。这段代码发现将第24位和“}”比较,第13位和“_”比较,第19位和“$”比较,相等跳到0040136B。至此我们可以修改输入字符为“XDCTF{123456_ABCDE$abcd}”。

;代码3.10040130F    83F9 7D         cmp ecx,0x7D    ; 第24位和“}”比较
00401312    74 1A           je Xctf2.0040132E
00401314    68 7CCA4000     push ctf2.0040CA7C                       ; ASCII "You shall not pass!"
00401319    E8 E3060000     call ctf2.00401A01
0040131E    83C4 04         add esp,0x4
00401321    E8 A5070000     call ctf2.00401ACB
00401326    83C8 FF         or eax,0xFFFFFFFF
00401329    E9 4A030000     jmp ctf2.00401678
0040132E    0FBE95 FCFEFFFF movsx edx,byte ptr ss:[ebp-0x104]
00401335    83FA 5F         cmp edx,0x5F   ; 第13位和“_”比较
00401338    75 0C           jnz Xctf2.00401346
0040133A    0FBE85 02FFFFFF movsx eax,byte ptr ss:[ebp-0xFE]
00401341    83F8 24         cmp eax,0x24    ; 第19位和“$”比较
00401344    74 1A           je Xctf2.00401360
00401346    68 7CCA4000     push ctf2.0040CA7C                       ; ASCII "You shall not pass!"
0040134B    E8 B1060000     call ctf2.00401A01
00401350    83C4 04         add esp,0x4
00401353    E8 73070000     call ctf2.00401ACB
00401358    83C8 FF         or eax,0xFFFFFFFF
0040135B    E9 18030000     jmp ctf2.00401678
00401360    74 09           je Xctf2.0040136B  ; 通过
00401362    75 12           jnz Xctf2.00401376   ; 不通过

4.验证7~12位

重新运行程序,输入“XDCTF{123456_ABCDE$abcd}”,程序如预期跳到0040136B,再跳到00401376(代码4.1),F8到0040145C处,程序将”XDCTF_”放入内存0040CA90。

继续往下分析,从00401090开始,进入第四阶段的验证(代码 4.2)。代码中标注了三行关键代码,004010AA处第一次验证指向的地址为0040CA90,此处的内存存放了“XDCTF_”(图 4.1);004010B3处第一次验证指向的地址为004010B3,存放了“123456”。004010B6处将“XDCTF_”和“123456”对应依次相减(ascii码),得到的结果在004010BE处与ds:[edx+ecx*4+0x8]中存储的数据比较,相等则通过验证。通过强制跳转分析,每一次相减得到的正确数值应为:

堆栈 ds:[0012FEF8]=00000015

堆栈 ds:[0012FEFC]=FFFFFFD5

堆栈 ds:[0012FF00]=FFFFFFD5

堆栈 ds:[0012FF04]=FFFFFFED

堆栈 ds:[0012FF08]=FFFFFFD4

堆栈 ds:[0012FF0C]=FFFFFFFE

即:7~12位正确的输入应为(需转换类型):

“X” - 0x00000015   =  “C”

“D” - 0xFFFFFFD5  =  “o”

“C” - 0xFFFFFFD5  =  “n”

“T” - 0xFFFFFFED  =  “g”

“F” - 0xFFFFFFD4  =  “r”

“_” - 0xFFFFFFFE  =  “a”

;代码4.10040145C    C785 ECFEFFFF 9>mov dword ptr ss:[ebp-0x114],ctf2.0040CA>; ASCII "XDCTF_"
00401466    6A 06           push 0x6
00401468    E8 12020000     call ctf2.0040167F
;代码4.2
00401090    8B45 F8         mov eax,dword ptr ss:[ebp-0x8]
00401093    83C0 01         add eax,0x1
00401096    8945 F8         mov dword ptr ss:[ebp-0x8],eax
00401099    8B4D FC         mov ecx,dword ptr ss:[ebp-0x4]
0040109C    83E9 01         sub ecx,0x1
0040109F    394D F8         cmp dword ptr ss:[ebp-0x8],ecx
004010A2    7F 26           jg Xctf2.004010CA
004010A4    8B55 08         mov edx,dword ptr ss:[ebp+0x8]
004010A7    0355 F8         add edx,dword ptr ss:[ebp-0x8]
004010AA    0FBE02       movsx eax,byte ptr ds:[edx] ; [0040CA90]-->”XDCTF_”
004010AD    8B4D 0C         mov ecx,dword ptr ss:[ebp+0xC]
004010B0    034D F8         add ecx,dword ptr ss:[ebp-0x8]
004010B3    0FBE11       movsx edx,byte ptr ds:[ecx] ;   [004010B3]-->”123456”
004010B6    2BC2            sub eax,edx              ;对应依次相减-->eax
004010B8    8B4D F8         mov ecx,dword ptr ss:[ebp-0x8]
004010BB    8B55 10         mov edx,dword ptr ss:[ebp+0x10]
004010BE    3B448A 08       cmp eax,dword ptr ds:[edx+ecx*4+0x8] ;eax是否与ds:[edx+ecx*4+0x8]中存储的数据是否相等
004010C2    74 04           je Xctf2.004010C8
004010C4    32C0            xor al,al
004010C6    EB 04           jmp Xctf2.004010CC
004010C8  ^ EB C6           jmp Xctf2.00401090

图 4.1

图 4.2

5.验证14~18位

F8继续往下,来到004010F1处(代码5.1),从这里开始将第14~18位依次与“t”“U”、“l”、“a”、“t”比较,相等则验证通过。

;代码5.1
004010F1    8955 F4         mov dword ptr ss:[ebp-0xC],edx
004010F4    8B45 08         mov eax,dword ptr ss:[ebp+0x8]
004010F7    8945 F0         mov dword ptr ss:[ebp-0x10],eax
004010FA    8B4D F0         mov ecx,dword ptr ss:[ebp-0x10]
004010FD    8A11            mov dl,byte ptr ds:[ecx]
004010FF    8855 EF         mov byte ptr ss:[ebp-0x11],dl
00401102    8B45 F4         mov eax,dword ptr ss:[ebp-0xC]
00401105    3A10            cmp dl,byte ptr ds:[eax]
00401107    75 2E           jnz Xctf2.00401137
00401109    807D EF 00      cmp byte ptr ss:[ebp-0x11],0x0
0040110D    74 1F           je Xctf2.0040112E
0040110F    8B4D F0         mov ecx,dword ptr ss:[ebp-0x10]
00401112    8A51 01         mov dl,byte ptr ds:[ecx+0x1]
00401115    8855 EE         mov byte ptr ss:[ebp-0x12],dl
00401118    8B45 F4         mov eax,dword ptr ss:[ebp-0xC]
0040111B    3A50 01         cmp dl,byte ptr ds:[eax+0x1]
0040111E    75 17           jnz Xctf2.00401137
00401120    8345 F0 02      add dword ptr ss:[ebp-0x10],0x2
00401124    8345 F4 02      add dword ptr ss:[ebp-0xC],0x2
00401128    807D EE 00      cmp byte ptr ss:[ebp-0x12],0x0
0040112C  ^ 75 CC           jnz Xctf2.004010FA

6.验证20~23位

继续往下跟踪,到004015D1处进入第6阶段验证。(代码 6.1)

“T”与第20个字符异或结果为0x31,该字符为“e”;

“C”与第21个字符异或结果为0x3A,该字符为“y”;

“D”与第22个字符异或结果为0xB,该字符为“W”

“X”与第23个字符异或结果为0x2D,该字符为“u”

;代码6.1
004015D1    0FBE8D DCFEFFFF movsx ecx,byte ptr ss:[ebp-0x124]   ; “e”
004015D8    0FBE95 F3FEFFFF movsx edx,byte ptr ss:[ebp-0x10D]   ;“T”
004015DF    33CA            xor ecx,edx
004015E1    83F9 31         cmp ecx,0x31          ;ecx=“e”⊕ “T”=0x31
004015E4    75 3F           jnz Xctf2.00401625
004015E6    0FBE85 DDFEFFFF movsx eax,byte ptr ss:[ebp-0x123] ;  ”y”
004015ED    0FBE8D F2FEFFFF movsx ecx,byte ptr ss:[ebp-0x10E]  ;”C”
004015F4    33C1            xor eax,ecx
004015F6    83F8 3A         cmp eax,0x3A         ;eax=“y”⊕ “C”=0x3A
004015F9    75 2A           jnz Xctf2.00401625
004015FB    0FBE95 DEFEFFFF movsx edx,byte ptr ss:[ebp-0x122]
00401602    0FBE85 F1FEFFFF movsx eax,byte ptr ss:[ebp-0x10F]
00401609    33D0            xor edx,eax
0040160B    83FA 0B         cmp edx,0xB        ; edx=“O”⊕ “D”=0xB
0040160E    75 15           jnz Xctf2.00401625
00401610    0FBE8D DFFEFFFF movsx ecx,byte ptr ss:[ebp-0x121]
00401617    0FBE95 F0FEFFFF movsx edx,byte ptr ss:[ebp-0x110]
0040161E    33CA            xor ecx,edx
00401620    83F9 2D         cmp ecx,0x2D        ;ecx=“u”⊕ “X”=0x2D
00401623    74 12           je Xctf2.00401637
00401625    68 98CA4000     push ctf2.0040CA98                       ; ASCII "You shall not pass!\n"
0040162A    E8 D2030000     call ctf2.00401A01
0040162F    83C4 04         add esp,0x4
00401632    E8 94040000     call ctf2.00401ACB
00401637    68 B0CA4000     push ctf2.0040CAB0                       ; ASCII "You do it!"
0040163C    E8 C0030000     call ctf2.00401A01

到这里,flag已浮出水面,赶紧输入一下,”you do it!”~~

Flag:   XDCTF{Congra_tUlat$eyOu}

Ps: 欢迎大家指正~

By. Vi

时间: 2024-10-12 08:55:26

2015_XDCTF_Reverse200_Writeup的相关文章