💾 Archived View for 0x80.org › gemlog › 2015-10-05-dctf-r400.gmi captured on 2022-04-28 at 17:40:46. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2021-12-03)

-=-=-=-=-=-=-

dctf r400

This challenge asks for a password. We see that it calls getenv to check for LD_PRELOAD, ptrace which are used to detect if a processes is debugged.

[0x00400875]> afl ~env
0x00400660  6  1  sym.imp.getenv
[0x00400875]> afl ~ptr
0x004006f0  6  1  sym.imp.ptrace

Since this is dynamic binary we can bypass these without patching via LD_PRELOAD, we let getenv return 0, and ptrace return 0 to bypass the protection.

#include <stdio.h>
int ptrace(int request, int pid, int addr, int data){
    return 0;
}
char *getenv(const char *name){
    return 0;
}

After asking for the password we reach this.

[0x006010a7]> pd 4
            0x006010a7    5e             pop rsi
            0x006010a8    6a00           push 0
            0x006010aa    59             pop rcx
            0x006010ab    eb03           jmp 0x6010b0

rsi point to a block of code bytes, rcx is a counter in that block.

[0x006010a7]> s 0x6010b0
[0x006010b0]> pd 2
            0x006010b0   xor dword [rsi + rcx], edx
            0x006010b3   jmp 0x6010b8

our input is xored with dword in the rsi[rcx]

[0x006010b0]> s 0x6010b8
[0x006010b8]> pd 6
       ||   0x006010b8   add ecx, 4
       ||   0x006010bb   cmp byte [rsi + rcx], 0xf0                    ; [0xf0:1]=0
       |`=< 0x006010bf   jne 0x6010ab
       |    0x006010c1   cmp byte [rsi + rcx + 1], 0xd                 ; [0xd:1]=0
       `==< 0x006010c6   jne 0x6010ab
            0x006010c8   jmp rsi

increment counter, then compare to see if we reached the end which is 0xf00d, and jump to rsi if we reached the end. rsi is pointing to this block : 0x6010D8-0x601129 which is supposed to be valid instructions after xoring. We dump the block for analysis to find the key.

[0x006010d8]> s 0x6010D8
[0x006010d8]> wt xored_block.bin 82
dumped 0x52 bytes
Dumped 82 bytes from 0x006010d8 into xored_block.bin

We assume the function contains at least int 0x80, and the key is printable. We write a script that searches for such thing

#!/usr/bin/env python2

from pwn import *
from string import printable

def main():
    xcode = open("xored_block.bin", "rb").read()
    for i in xrange(0, 0xff):
        for j in xrange(0,0xff):
            k = chr(i)+chr(j)
            if "\xcd\x80" in xor(xcode, k) and \
            all(c in printable for c in k):
                print "Found : ", k
if __name__ == "__main__":
    main()


➜  r400  python2 find.py     
Found :  4b
Found :  ;&
Found :  fb
Found :  pk
Found :  v/

These are the possible beginning of the key, we use them and it seems '4b' is the one that makes sense here. Applying the key and looking at the disassembly, trying to make sense of the rest of it reveals that it's 'f6', we can also use the above script to find the last two characters by looking at 0x9090.

➜  r400  r2 -w xored_block.bin
 -- Excellent; we can attack in any direction!
[0x00000000]> wox 0x34626636
[0x00000000]> aaa
[0x00000000]> afl
0x00000000  80  1  fcn.00000000
[0x00000000]> pdf fcn.00000000
/ (fcn) fcn.00000000 80
|           0x00000000    6a0a           push 0xa
|           0x00000002    686f726421     push 0x2164726f
|           0x00000007    6861737377     push 0x77737361
|           0x0000000c    6868652070     push 0x70206568
|           0x00000011    686e642074     push 0x7420646e
|           0x00000016    6820666f75     push 0x756f6620
|           0x0000001b    6820596f75     push 0x756f5920
|           0x00000020    686f6e7321     push 0x21736e6f
|           0x00000025    686c617469     push 0x6974616c
|           ; DATA XREF from 0x00000034 (fcn.00000000)
|           0x0000002a    6872617475     push 0x75746172
|           0x0000002f    68436f6e67     push 0x676e6f43
|           0x00000034    ba2a000000     mov edx, 0x2a                 ; '*'
|           0x00000039    89e1           mov ecx, esp
|           0x0000003b    bb01000000     mov ebx, 1
|           0x00000040    b804000000     mov eax, 4
|           0x00000045    cd80           int 0x80                      ;read (0x0,0x0,0x0) ; fcn.00000000+-1
|           0x00000047    b801000000     mov eax, 1
|           0x0000004c    cd80           int 0x80                      ;read (0x0,0x0,0x0) ; fcn.00000000+-1
|           0x0000004e    90             nop
\           0x0000004f    90             nop

password : 4bf6.

➜  r400  echo -ne '436f6e67726174756c6174696f6e732120596f7520666f756e64207468652070617373776f726421' | rax2 -s
Congratulations! You found the password