【问题标题】:x86 Assembly EIP Value not displaying in readable formatx86 程序集 EIP 值未以可读格式显示
【发布时间】:2019-05-09 11:52:18
【问题描述】:

我正在分析一段汇编代码以提取密钥。 源代码如下,但我正在做的是在 pop esp 指令之后设置断点,然后尝试检查堆栈以确定 128 位密钥。

我的汇编知识还很初级,但我认为正在发生的事情是程序用DWORD 指令的开头系列构造密钥,然后将其加载到堆栈中。

问题在于输出。我在pop esp 调用后中断,检查堆栈,但都是“乱码”。

我想这是我想要的字符串:0xffffd21c ("#'%px$rr 'q#rq' r\"u$w%vsp\"p\"y#$v' twy#q$yt'p'x$psu \"ww' y'v' srr$#xtvqt$s \"uyt\"pxptuwsr'stry\"v'\"rrw\"ptpwvy''y 'x\"y wrys\"rqq\"uyvv")

我的问题是,我对执行的理解是错误的吗?为什么?如何更正从esp 的乱码字符中提取人类可读字符串的过程?

我的 GDB/PEDA 输出...

root@kali:~/ctp/challenge# gdb ./key 
GNU gdb (GDB) 8.2
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./key...done.
gdb-peda$ break *0x565560a4
Breakpoint 1 at 0x565560a4
gdb-peda$ r
Starting program: /root/ctp/challenge/key 



[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0xf7ffd000 --> 0x28f2c 
ECX: 0x0 
EDX: 0xf7fe4560 (push   ebp)
ESI: 0xffffd2ac --> 0xffffd468 ("SHELL=/bin/bash")
EDI: 0x56556000 (<_start>:  xor    eax,eax)
EBP: 0x0 
ESP: 0xffffd218 --> 0xffffd21c ("#'%px$rr 'q#rq' r\"u$w%vsp\"p\"y#$v' twy#q$yt'p'x$psu \"ww' y'v' srr$#xtvqt$s \"uyt\"pxptuwsr'stry\"v'\"rrw\"ptpwvy''y 'x\"y wrys\"rqq\"uyvv")
EIP: 0x565560a4 (<_start+164>:  pop    esi)
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x56556099 <_start+153>: push   0x72722478
   0x5655609e <_start+158>: push   0x70252723
   0x565560a3 <_start+163>: push   esp
=> 0x565560a4 <_start+164>: pop    esi
   0x565560a5 <_start+165>: mov    edi,esi
   0x565560a7 <_start+167>: mov    edx,edi
   0x565560a9 <_start+169>: cld    
   0x565560aa <_start+170>: mov    ecx,0x80
[------------------------------------stack-------------------------------------]
0000| 0xffffd218 --> 0xffffd21c ("#'%px$rr 'q#rq' r\"u$w%vsp\"p\"y#$v' twy#q$yt'p'x$psu \"ww' y'v' srr$#xtvqt$s \"uyt\"pxptuwsr'stry\"v'\"rrw\"ptpwvy''y 'x\"y wrys\"rqq\"uyvv")
0004| 0xffffd21c ("#'%px$rr 'q#rq' r\"u$w%vsp\"p\"y#$v' twy#q$yt'p'x$psu \"ww' y'v' srr$#xtvqt$s \"uyt\"pxptuwsr'stry\"v'\"rrw\"ptpwvy''y 'x\"y wrys\"rqq\"uyvv")
0008| 0xffffd220 ("x$rr 'q#rq' r\"u$w%vsp\"p\"y#$v' twy#q$yt'p'x$psu \"ww' y'v' srr$#xtvqt$s \"uyt\"pxptuwsr'stry\"v'\"rrw\"ptpwvy''y 'x\"y wrys\"rqq\"uyvv")
0012| 0xffffd224 (" 'q#rq' r\"u$w%vsp\"p\"y#$v' twy#q$yt'p'x$psu \"ww' y'v' srr$#xtvqt$s \"uyt\"pxptuwsr'stry\"v'\"rrw\"ptpwvy''y 'x\"y wrys\"rqq\"uyvv")
0016| 0xffffd228 ("rq' r\"u$w%vsp\"p\"y#$v' twy#q$yt'p'x$psu \"ww' y'v' srr$#xtvqt$s \"uyt\"pxptuwsr'stry\"v'\"rrw\"ptpwvy''y 'x\"y wrys\"rqq\"uyvv")
0020| 0xffffd22c ("r\"u$w%vsp\"p\"y#$v' twy#q$yt'p'x$psu \"ww' y'v' srr$#xtvqt$s \"uyt\"pxptuwsr'stry\"v'\"rrw\"ptpwvy''y 'x\"y wrys\"rqq\"uyvv")
0024| 0xffffd230 ("w%vsp\"p\"y#$v' twy#q$yt'p'x$psu \"ww' y'v' srr$#xtvqt$s \"uyt\"pxptuwsr'stry\"v'\"rrw\"ptpwvy''y 'x\"y wrys\"rqq\"uyvv")
0028| 0xffffd234 ("p\"p\"y#$v' twy#q$yt'p'x$psu \"ww' y'v' srr$#xtvqt$s \"uyt\"pxptuwsr'stry\"v'\"rrw\"ptpwvy''y 'x\"y wrys\"rqq\"uyvv")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x565560a4 in _start ()
gdb-peda$ x/10s $esp
0xffffd218: "\034\322\377\377#'%px$rr 'q#rq' r\"u$w%vsp\"p\"y#$v' twy#q$yt'p'x$psu \"ww' y'v' srr$#xtvqt$s \"uyt\"pxptuwsr'stry\"v'\"rrw\"ptpwvy''y 'x\"y wrys\"rqq\"uyvv"
0xffffd29d: ""
0xffffd29e: ""
0xffffd29f: ""
0xffffd2a0: "\001"
0xffffd2a2: ""
0xffffd2a3: ""
0xffffd2a4: "P\324\377\377"
0xffffd2a9: ""
0xffffd2aa: ""
gdb-peda$ 

代码...

global _start
_start:
    xor eax,eax
    push eax
    push dword 0x76767975
    push dword 0x22717172
    push dword 0x22737972
    push dword 0x77207922
    push dword 0x78272079
    push dword 0x27277976
    push dword 0x77707470
    push dword 0x22777272
    push dword 0x22277622
    push dword 0x79727473
    push dword 0x27727377
    push dword 0x75747078
    push dword 0x70227479
    push dword 0x75222073
    push dword 0x24747176
    push dword 0x74782324
    push dword 0x72727320
    push dword 0x27762779
    push dword 0x20277777
    push dword 0x22207573
    push dword 0x70247827
    push dword 0x70277479
    push dword 0x24712379
    push dword 0x77742027
    push dword 0x76242379
    push dword 0x22702270
    push dword 0x73762577
    push dword 0x24752272
    push dword 0x20277172
    push dword 0x23712720
    push dword 0x72722478
    push dword 0x70252723
    push esp
    pop esi
    mov edi,esi
    mov edx,edi
    cld
    mov ecx,0x80
    mov ebx,0x41
    xor eax,eax
    push eax
    lodsb
    xor eax,ebx
    stosb
    ;loop 0xb7 ; offending line
    ;dec ecx
    jnz 0xb7; added in
    push esp
    pop esi
    int3
    db 0x0a

【问题讨论】:

  • 不确定您正在运行的代码版本。使用 both loop 和 dec ecx 注释掉代码将不会只处理第一个字符的字符串。再三考虑,这将取决于 xor 结果,这不太可能是您想要的。
  • 另外,显然你不理解 cmets 和我在 your previous question 上的回答。您实际上不想要jnz 0xb7,这将跳转到绝对地址0xb7 和段错误。我指出这是为了说明您所写内容的含义以及组装+链接的工作原理。
  • 这看起来应该只是一个用0x41异或0x80字节的愚蠢循环。显然,在循环中使用xor dword [esi], 0x41414141 / add esi, 4 可以更有效地完成,或者使用稍小的代码大小以不同的方式打高尔夫球(例如使用lodsd 来增加ESI)。循环让我想到优化代码大小,但mov ecx, imm32 是反对这一点的有力证据。有趣的一点是jnz 将始终被采用,因为 XOR 将始终使用该数据产生非零结果。
  • 它们没有乱码,那些(大概)将这些字节正确解释为 ASCII 字符。你说你想要 EIP 值(即使它们在 EIP 中 not 也是利用返回地址来表示......),但它看起来像字符串数据。例如0x70 ^ 0x41 = 0x31 = '1'。和0x23^0x41 = 0x62 = 'b'。实际的 EIP 显示很好:EIP: 0x565560a4 (&lt;_start+164&gt;: pop esi)。如果堆栈确实保存了返回地址,您将使用 x /10xw $esp 或类似名称。

标签: assembly gdb elf


【解决方案1】:

它们没有乱码,那些(大概)将这些字节正确解释为 ASCII 字符。

并且它们不是一个或多个 EIP 值。 (“EIP 值”有时会被利用来代替返回地址,即使它们在 EIP 中不是,但我认为这里不会发生这种情况)。实际 EIP 显示正常:EIP: 0x565560a4 (&lt;_start+164&gt;: pop esi)。

如果堆栈确实保存了返回地址,您将使用 x /10xw $esp 或类似名称。

它看起来像字符串数据。例如0x70 ^ 0x41 = 0x31 = '1'。和0x23^0x41 = 0x62 = 'b'。

但我认为正在发生的事情是程序使用一系列 DWORD 指令构造密钥,然后将其加载到堆栈中。

不,它通过一系列推送来构造堆栈上的数据。那时它已经在堆栈上。

密钥是0x41,在mov ebx, 0x41。


然后看起来它有一个效率低下的循环,应该 xor 每次一个字节与 0x41,但是您注释掉了 dec 并留在分支中的绝对地址 0xb7在 Linux 下会出现段错误。

应该是这样的

.loop:            ; do {
   lodsb
   xor  eax,ebx
   stosb
   dec  ecx
   jnz  .loop     ; }while(--ecx);

在前面设置EDI和ESI = ESP的指令之后,清除DF到字符串指令向上。

这是非常低效的(对于 ECX = 0x80 字节,一次 1 个字节并使用慢速 loop 指令,该指令将其限制为在最近的 Intel CPU 上每 6 个周期进行 1 次迭代),但看起来也没有针对代码大小。 (mov eax, 0x41 是 5 个字节,而 push 0x41 / pop eax 是 3 个字节)。优化循环的代码大小,但代码外部的速度是倒退的。

效率更高的是xor dword [esi], 0x41414141 / add esi,4。 (或者,如果您关心代码大小而不是速度,则可以使用 lodsd 作为 1 字节的方式将 ESI 增加 4。)

【讨论】:

  • 我回家后会测试一下。抱歉,我之前误解了你所说的标签的意思。我认为label == memory address 而不是循环“区域”的实际标签。还有dec ecx 指令,我说得对吗?它正在减少jnz 然后评估循环继续/中断的ecx(计数器)吗?
  • @RichC:不,jnz 在 EFLAGS 中读取 ZF。 (dec ecx 根据--ecx 的结果设置)。 felixcloutier.com/x86/index.html。或者查找任何关于 x86 asm 分支和循环如何工作的不错的教程或书籍。
  • 用cld“重置”EFLAGS 中的 ZF?然后... 使用此设置将字符串加载到eax? push eax / lodsb / xor eax,ebx / stosb。 push,eax,将字符串加载到 eax,与 0x41 进行异或运算,然后存储字符串。我看不到最终收集的长度为 0x80 的字符串的存储位置。抱歉有一千个问题,只是想确保我理解正确!
  • @RichC:不,cld 清除 DF。 ZF 是条件代码标志之一。再次,查找有关 x86 标志和分支的任何体面的教程或文档。我不确定在循环之前推送一个额外的零双字有什么意义。 (但它是在设置 ESI 和 EDI 之后,所以它不是循环处理的一部分。)请注意 lodsb 仅加载到 AL 中。无论如何,字符串已经保存在堆栈中,只是在原地修改。使用调试器单步执行代码,并观察寄存器值的变化。例如gdb 和 layout reg,或者任何你喜欢的。
  • 会的。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-24
  • 1970-01-01
  • 2011-07-20
  • 2016-01-23
  • 1970-01-01
  • 2014-05-30
  • 1970-01-01
相关资源
最近更新 更多