【问题标题】:Questions on learning assembly for a CTF challenge关于 CTF 挑战的学习组装问题
【发布时间】:2018-04-25 05:57:14
【问题描述】:

我刚刚开始参与 Assembly 以应对 CTF 逆转挑战,并且玩得很开心。然而,我正在处理的当前挑战让我很难过 - 希望有人可以帮助解决一些基本的装配问题 - 或者向我指出好的资源。

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

该函数以相当简单的方式开始 - 我已经添加了我自己的 cmets 以尽我的理解:

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 需要传递第三块代码?

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

谢谢!

【问题讨论】:

    标签: assembly x86


    【解决方案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'。

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

    是的,您在地址下的第一个块中有该代码/模式:080486880804868b。没有add eax,1,其余的都是一样的。

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

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

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

    【讨论】:

    • 谢谢 - 这非常有帮助。
    • 我可以问一个后续问题吗?如果add eax, 0x1 将 eax 指向输入缓冲区中的第二个字符,这是否意味着 movzx eax, byte [eax] without add eax, 0x1 指向缓冲区中的 first 字符?另外,dword [ebp+0x8 {arg1}] 是否总是表示输入缓冲区,还是仅在这种情况下?最后,感谢您向我介绍逆向工程 - 我不确定该社区是否仅涵盖实际的逆向工程,而不包括练习和 CTF 挑战。
    • 查看我的更新答案;如果你觉得这很有用,请投票,如果它回答了你的问题,请标记它。
    • 太棒了。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2011-03-28
    • 2017-03-23
    • 1970-01-01
    • 2010-12-22
    • 2021-02-03
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    相关资源
    最近更新 更多