关于为CTF挑战学习集会的问题

时间:2018-04-24 16:29:48

标签: assembly x86

我刚刚开始参加大会,以寻求CTF逆转挑战,并且我玩得很开心。我正在努力的当前挑战让我感到难过 - 希望有人可以帮助解决一些基本的大会问题 - 或者指出我的资源。

我通过Binary Ninja运行了为挑战提供的二进制文件,并确定了关键函数 - 在该函数中跟踪逻辑给我带来了问题。

该功能以一种相当直接的方式开始 - 我已经根据我的理解添加了自己的评论:

08048661  push    ebp {__saved_ebp}  ;Push old base pointer onto stack
08048662  mov     ebp, esp {__saved_ebp} ;Function preamble (?) 
08048664  sub     esp, 0x18
08048667  sub     esp, 0xc
0804866a  push    dword [ebp+0x8 {arg1}] {var_2c} ;var_2c is user input (arg1)
0804866d  call    strlen ;Get the string length of user input
08048672  add     esp, 0x10 ;?? 
08048675  mov     dword [ebp-0x10 {var_14}], eax  ;Assign EAX to var_14
08048678  cmp     dword [ebp-0x10 {var_14}], 0x13 
;Compares string length to 0x13 (decimal 19) - if it's longer continue
0804867c  ja      0x8048688

第一个块似乎得到用户输入的字符串长度 - 如果字符串长度大于19,则继续到下一个块。

下一个区块是我认为我的理解不正确的地方:

08048688  mov     eax, dword [ebp+0x8 {arg1}]     
;Set EAX to the memory location of the user input (arg1) 
0804868b  movzx   eax, byte [eax]         
;Replace EAX with the first byte of EAX (arg1)
0804868e  cmp     al, 0x61            
;Compare the first byte of EAX with 0x61 (decimal 97 / binary 01100001)
;if equal, continue to next block
08048690  je      0x8048699

这意味着正确响应的第一个字节必须是01100001 - 但这似乎与下一个块相矛盾:

08048699  mov     eax, dword [ebp+0x8 {arg1}] 
;Set EAX to the memory location of the user input (arg1)
0804869c  add     eax, 0x1 
;Add 0x1 to EAX (decimal 1 / binary 00000001)
0804869f  movzx   eax, byte [eax]
;Replace EAX with only the first byte of EAX (arg1+1)
080486a2  cmp     al, 0x71           
;Compare the first byte of EAX with 0x71 (decimal 113 / binary 01110001)
;if equal, continue to next block
080486a4  je      0x80486ad

这是我目前卡住的地方 - 如果输入的第一个字节需要十进制97 /二进制01100001才能通过第二个块,那么如何向它添加1可能会导致小数113 /二进制01110001需要传递第三块代码?

我不确定我对代码的理解是不正确的 - 非常感谢任何提示或指示。如果这涵盖了基本知识,请道歉 - 我正在自己解决这些问题。

谢谢!

1 个答案:

答案 0 :(得分:1)

好吧,它没有添加应该导致113的一个。如果你仔细观察,你应该注意到在1再次读取字符值之前已经eax添加了eax。仅将此新加载的值与0x71进行比较。所以这第一个操作只是作为一个索引增量。

更多解释:

08048699  mov     eax, dword [ebp+0x8 {arg1}] 

这会将输入缓冲区的地址加载到eax

0804869c  add     eax, 0x1 

eax指向输入缓冲区中的第二个字符。

0804869f  movzx   eax, byte [eax]

此行将eax指向(输入缓冲区)的字符加载到eax(用零扩展到32位)。

只有在最后一行之后,您才能与0x71进行比较。所以第二个字符应该是' q'。

  

如果添加eax,0x1将eax指向输入缓冲区中的第二个字符,这是否意味着movzx eax,byte [eax]没有添加eax,0x1指向缓冲区中的第一个字符?

是的,您在地址下的第一个区块中拥有该代码/模式:08048688& 0804868b。没有add eax,1,其余的都是相同的。

  

dword [ebp+0x8 {arg1}]总是表示输入缓冲区,还是仅在这种情况下?

只有在这种情况下 - 这个[ebp+0x8]基本上指向堆栈上的参数 - 在这种情况下它是输入缓冲区,但它不必像那样。

顺便说一句,我认为你在Reverse Engineering上提出这些问题会更好。