c-跳到argv吗?

我正在尝试shellcode,偶然发现了nop-slide技术.我写了一个小工具,将buffer-size作为参数并像这样构造一个缓冲区:[NOP | SC | RET],NOP占用缓冲区的一半,然后是shellcode,其余的则填充(猜测的)返回地址.它与他的著名论文中描述的工具aleph1非常相似.

我脆弱的测试应用程序与他的论文相同:

int main(int argc, char **argv) {
char little_array[512];
if(argc>1)
    strcpy(little_array,argv[1]);   
return 0;
}

我测试了一下,效果很好:

jth@insecure:~/no_nx_no_aslr$./victim $(./exploit 604 0)
$exit

但老实说,我不知道为什么.好的,保存的eip已按预期被覆盖,但我认为它没有跳到缓冲区中,而是跳到了argv中.

gdb在调用strcpy()之前显示了以下地址:

(gdb) i f  
Stack level 0, frame at 0xbffff1f0:  
 eip = 0x80483ed in main (victim.c:7); saved eip 0x154b56  
 source language c.  
 Arglist at 0xbffff1e8, args: argc=2, argv=0xbffff294  
 Locals at 0xbffff1e8, Previous frame's sp is 0xbffff1f0  
 Saved registers:  
  ebp at 0xbffff1e8, eip at 0xbffff1ec  

little_array的地址:

(gdb) print &little_array[0]
 $1 = 0xbfffefe8 "\020"

在strcpy()之后:

(gdb) i f
Stack level 0, frame at 0xbffff1f0:
 eip = 0x804840d in main (victim.c:10); saved eip 0xbffff458
 source language c.
 Arglist at 0xbffff1e8, args: argc=-1073744808, argv=0xbffff458
 Locals at 0xbffff1e8, Previous frame's sp is 0xbffff1f0
 Saved registers:
  ebp at 0xbffff1e8, eip at 0xbffff1ec

那么,这里发生了什么?我使用了604字节的缓冲区来溢出little_array,因此他当然重写了保存的ebp,保存的eip和argc以及带有猜测地址0xbffff458的argv.

然后,返回后,EIP指向0xbffff458.但是little_buffer位于0xbfffefe8,相差1136个字节,因此他当然没有执行little_array.我使用stepi命令跟踪执行,然后从0xbffff458开始,他执行NOP并到达Shellcode.

我不太确定为什么会这样.首先,我是否正确说他在argv中而不是little_array中执行我的shellcode? loader(?)将argv放在哪里?我以为它紧随argc之后,但是在argc和0xbffff458之间,有620个字节的间隙.他怎么可能成功地“降落”在地址为0xbffff458的NOP面板中,该地址比保存的eip高于0xbffff1ec的地址高?

有人可以澄清吗?我实际上不知道为什么这样做.我的测试机器是没有ASLR的Ubuntu 9.10 32位机器.受害者有一个可执行栈,用execstack -s设置.

提前致谢.

解决方法:

首先,绘制堆栈图.

0xBFFFF4F9 |          |
            ----------
          ...   
0xBFFFF29E |    NOP   |
0xBFFFF29D |    NOP   | argv[1]   * guestimate
            ----------
0xBFFFF29C |   '\0'   |
          ...
0xBFFFF295 |    '/'   |
0xBFFFF294 |    '.'   | argv[0] "./victim"
            ----------
          ... 
            ----------
0xBFFFF1F8 |   NULL   |
0xBFFFF1F8 | &argv[1] |
0xBFFFF1F4 | &argv[0] | argv
            ---------- 
0xBFFFF1F0 | 0x000002 | argc
            ---------- 
          ...
0xBFFFEFE9 |          |
0xBFFFEFE8 |          | little_array
            ----------

(注意:在图中,某些框每行保留1个字节,其他框为4或8,这取决于存储在其中的类型)

And where does the loader(?) place argv onto the stack?

在调用strcpy表明它们可能在little_array之上之后,argc和argv被覆盖.我将它们放置在0xBFFFF1F0处,因为那是堆栈在上一帧结束的地方,而且main的帧中似乎没有空间,即使GDB表示arglist位于0xBFFFF1E8.它依赖于我的系统-argc和argv低于little_array.尝试使用p& argv和p& argc来确定它们的放置位置.

由于0xBFFFF458位于argv [1]中,因此argv [1]中的shellcode确实是要执行的内容,而不是little_array中的内容.由于有两个shell代码副本(一个在little_array中,另一个在argv [1]中),根据您猜测的返回地址,可以执行其中一个.

I thought [argv] follows immediately after argc, but between argc and 0xbffff458, there is a gap of 620 bytes.

0xBFFFF458是漏洞利用后存储在argv中的值(请注意,argc与(带符号的)0xBFFFF458 == -1073744808相同).之前,argv持有0xbffff294.在这两种情况下,argv本身都存储在其他位置.

上一篇:RoR深入探索——Tale Wiki


下一篇:gym 102586 B Evacuation