Babyrev is reversing challenge on CSAW «Red team competition» where have to pass 99 rounds of input 4-digits code based on some check function.
Main graph on IDA:
Disassembly of check():
Dump of assembler code for function check: 0x0000000000400893 <+0>: push rbp 0x0000000000400894 <+1>: mov rbp,rsp 0x0000000000400897 <+4>: mov QWORD PTR [rbp-0x8],rdi 0x000000000040089b <+8>: mov QWORD PTR [rbp-0x10],rsi 0x000000000040089f <+12>: mov rcx,QWORD PTR [rbp-0x8] 0x00000000004008a3 <+16>: movabs rdx,0xa3d70a3d70a3d70b 0x00000000004008ad <+26>: mov rax,rcx 0x00000000004008b0 <+29>: imul rdx 0x00000000004008b3 <+32>: lea rax,[rdx+rcx*1] 0x00000000004008b7 <+36>: sar rax,0x6 0x00000000004008bb <+40>: mov rdx,rax 0x00000000004008be <+43>: mov rax,rcx 0x00000000004008c1 <+46>: sar rax,0x3f 0x00000000004008c5 <+50>: sub rdx,rax 0x00000000004008c8 <+53>: mov rax,rdx 0x00000000004008cb <+56>: shl rax,0x2 0x00000000004008cf <+60>: add rax,rdx 0x00000000004008d2 <+63>: lea rdx,[rax*4+0x0] 0x00000000004008da <+71>: add rax,rdx 0x00000000004008dd <+74>: shl rax,0x2 0x00000000004008e1 <+78>: sub rcx,rax 0x00000000004008e4 <+81>: mov rdx,rcx 0x00000000004008e7 <+84>: xor rdx,QWORD PTR [rbp-0x10] 0x00000000004008eb <+88>: mov rax,rdx 0x00000000004008ee <+91>: add rax,rax 0x00000000004008f1 <+94>: add rax,rdx 0x00000000004008f4 <+97>: cmp rax,0x1338 0x00000000004008fa <+103>: sete al 0x00000000004008fd <+106>: pop rbp 0x00000000004008fe <+107>: ret End of assembler dump.
Check in pseudo-code from IDA:
Per each round is generating a XOR key and with our input must be 0x1338 value. Something like:
3*(input^key[i])=0x1338
So can define a hook stop on gdb for printing all XOR values on all the rounds, setting $rax as 0x1338. It’s important to make outside the hook a break on cmp statement inside check function(b *check+84). Thanks to Manuel Blanco (@Manuelbp01) for collaborating on this steps.
gdb-peda$ define hook-stop Type commands for definition of "hook-stop". End with a line saying just "end". >p/d $rdx ^ 1640 >set $rax = 0x1338 >set $rip = check+97 >end gdb-peda$ b *check+84 Breakpoint 1 at 0x4008e7
Now we can continue to see all 99 4-digits values running with:
gdb-peda$ r <<< $(python -c 'print "\n" * 99')
Welcome to BabyRev can you crack the code??? $2 = 1595 YAAAY Keep GOING !! Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ c $3 = 1598 YAAAY Keep GOING !! Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ $4 = 1573 YAAAY Keep GOING !! Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ $5 = 1639 YAAAY Keep GOING !! Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ $6 = 1589 YAAAY Keep GOING !! Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ $7 = 1611 YAAAY Keep GOING !! Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ $8 = 1598 YAAAY Keep GOING !! Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ $9 = 1588 YAAAY Keep GOING !! Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ $10 = 1625 YAAAY Keep GOING !! Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ $11 = 1661 YAAAY Keep GOING !! Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ $12 = 1622 YAAAY Keep GOING !! Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ $13 = 1651 YAAAY Keep GOING !! Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ $14 = 1586 YAAAY Keep GOING !! Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ $15 = 1619 YAAAY Keep GOING !! Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ $16 = 1623 YAAAY Keep GOING !! [...] Breakpoint 1, 0x00000000004008e7 in check () gdb-peda$ $101 = 1615 YAAAY Keep GOING !! ERROR: no flag found. If you're getting this error on the remote system, please message the admins. If you're seeing this locally, run it on the remote system! You solved the challenge, and need to get the flag from there! [Inferior 1 (process 8607) exited normally]
Have all codes to submit on the target machine. Prepare a script to do that:
#!/usr/bin/python from pwn import * def main(): nums = [1595, 1598, 1573, 1639, 1589, 1611, 1598, 1588, 1625, 1661, 1622, 1651, 1586, 1619, 1623, 1650, 1600, 1650, 1568, 1612, 1635, 1580, 1579, 1653, 1594, 1654, 1622, 1663, 1579, 1611, 1653, 1642, 1662, 1618, 1581, 1579, 1589, 1616, 1635, 1602, 1653, 1569, 1661, 1659, 1596, 1613, 1546, 1648, 1639, 1582, 1637, 1650, 1587, 1592, 1616, 1569, 1622, 1582, 1544, 1593, 1645, 1649, 1596, 1651, 1612, 1645, 1606, 1653, 1637, 1617, 1648, 1591, 1594, 1605, 1638, 1579, 1610, 1576, 1603, 1626, 1599, 1632, 1572, 1574, 1584, 1596, 1643, 1627, 1630, 1547, 1608, 1620, 1572, 1580, 1615, 1636, 1650, 1598, 1590, 1615] p = remote("reversing.chal.csaw.io", 10102) numbers = ''.join([str(num) + '\n' for num in nums]) p.send(numbers) data = p.recvline() while "flag" not in data: p.recvline() p.interactive() # avoid EOF error if __name__ == "__main__": main()
Here's your flag, friend: flag{60od_job_B4by_r3VeRzyng_C0mPl3tE!}
Si queréis probar el babyrev lo tenéis aquí