Showing posts with label write-up. Show all posts
Showing posts with label write-up. Show all posts

Sunday, August 4, 2013

ebCTF 2013: bin100 - bin300

bin100 - 'Dice Revenge'

Very similar challenge to one from teaser, roll some dices and win. Of course you have to roll 3 1 3 3 7 ;]
All rolls look alike:
 8048ebb:       e8 50 fc ff ff          call   8048b10 
 8048ec0:       89 c1                   mov    ecx,eax
 8048ec2:       ba ab aa aa 2a          mov    edx,0x2aaaaaab
 8048ec7:       89 c8                   mov    eax,ecx
 8048ec9:       f7 ea                   imul   edx
 8048ecb:       89 c8                   mov    eax,ecx
 8048ecd:       c1 f8 1f                sar    eax,0x1f
 8048ed0:       29 c2                   sub    edx,eax
 8048ed2:       89 d0                   mov    eax,edx
 8048ed4:       01 c0                   add    eax,eax
 8048ed6:       01 d0                   add    eax,edx
 8048ed8:       01 c0                   add    eax,eax
 8048eda:       89 ca                   mov    edx,ecx
 8048edc:       29 c2                   sub    edx,eax
 8048ede:       8d 42 01                lea    eax,[edx+0x1]
 8048ee1:       89 44 24 50             mov    DWORD PTR [esp+0x50],eax
 8048ee5:       83 7c 24 50 01          cmp    DWORD PTR [esp+0x50],0x1
So just find 5 rands and put breaks on them:
mov    DWORD PTR [esp+0x50],eax
Something like this:
--- bin100.gdb ---
b *0x8048ee1
b *0x80490ee
b *0x80492fc
b *0x80494ff
b *0x8049744

commands 1
set $eax=3
c
end

commands 2
set $eax=1
c
end
commands 3
set $eax=3
c
end
commands 4
set $eax=3
c
end

commands 5
set $eax=7
c
end

run
quit
--- end --- 
Fire it up: gdb -q -nx -x bin100.gdb bin100 press some enters aaand...
[*] You rolled a seven, with a six sided dice! How awesome are you?!
[*] You rolled 3-1-3-3-7, what does that make you? ELEET! \o/
[*] Nice job, here is the flag: ebCTF{9a9689dbd47a1fd3fc0bf17d60edf545}

bin200 - 'No comment...'

Throw it in IDA, look around. Google for RunPerl or -p2x-exe/debug to find out its a perl script compiled
with perl2exe - you can find a decoder here - then run it:
$ python2 per2exe-dec.py ebCTF_BIN200.exe
p2x_stub.lib
p2x_header.pm
p2x_info.pm
_main.pl
P2XDLL/p2x5123.dl
$ cat _main.pl
#!/usr/bin/perl

print "\n[*] ebCTF BIN 200\n".
      "      No comment...\n\n";

$secret = "Sup3RSeCr3tStuFf!";

print "[*] What is the secret? ";
$answer = ;
chomp($answer);

if ($answer eq $secret) {
  print "\n[*] Yes, that is correct! However that was not the goal of this challenge.\n".
        "    Did you know that compiled code does not contain any comments?\n";
} else {
 print "\n[*] Isn't that cute...but it is WRONG!.\n";
}

# W e l l ,  w e l l,  i t  s e e m s  t h e r e  a c t u a l l y  i s  a  c o m m e n t . . .
#
# .----------------. .----------------. .----------------. .----------------.
#| .--------------. | .--------------. | .--------------. | .--------------. |
#| |  _________   | | |   ______     | | |     ______   | | |  _________   | |
#| | |_   ___  |  | | |  |_   _ \    | | |   .' ___  |  | | | |  _   _  |  | |
#| |   | |_  \_|  | | |    | |_) |   | | |  / .'   \_|  | | | |_/ | | \_|  | |
#| |   |  _|  _   | | |    |  __'.   | | |  | |         | | |     | |      | |
#| |  _| |___/ |  | | |   _| |__) |  | | |  \ `.___.'\  | | |    _| |_     | |
#| | |_________|  | | |  |_______/   | | |   `._____.'  | | |   |_____|    | |
#| |              | | |              | | |              | | |              | |
#| '--------------' | '--------------' | '--------------' | '--------------' |
# '----------------' '----------------' '----------------' '----------------'
# .----------------. .----------------. .----------------. .----------------.
#| .--------------. | .--------------. | .--------------. | .--------------. |
#| |  _________   | | |       __     | | |  _________   | | |  ________    | |
#| | |_   ___  |  | | |     .' _/    | | | |_   ___  |  | | | |_   ___ `.  | |
#| |   | |_  \_|  | | |     | |      | | |   | |_  \_|  | | |   | |   `. \ | |
#| |   |  _|      | | |    < <       | | |   |  _|  _   | | |   | |    | | | |
#| |  _| |_       | | |     | |_     | | |  _| |___/ |  | | |  _| |___.' / | |
#| | |_____|      | | |     `.__\    | | | |_________|  | | | |________.'  | |
#| |              | | |              | | |              | | |              | |
#| '--------------' | '--------------' | '--------------' | '--------------' |
# '----------------' '----------------' '----------------' '----------------'
# .----------------. .----------------. .----------------. .----------------.
#| .--------------. | .--------------. | .--------------. | .--------------. |
#| |   ______     | | |  ________    | | |   ______     | | |     ____     | |
#| |  |_   _ \    | | | |_   ___ `.  | | |  |_   _ \    | | |   .'    '.   | |
#| |    | |_) |   | | |   | |   `. \ | | |    | |_) |   | | |  |  .--.  |  | |
#| |    |  __'.   | | |   | |    | | | | |    |  __'.   | | |  | |    | |  | |
#| |   _| |__) |  | | |  _| |___.' / | | |   _| |__) |  | | |  |  `--'  |  | |
#| |  |_______/   | | | |________.'  | | |  |_______/   | | |   '.____.'   | |
#| |              | | |              | | |              | | |              | |
#| '--------------' | '--------------' | '--------------' | '--------------' |
# '----------------' '----------------' '----------------' '----------------'
# .----------------. .----------------. .----------------. .----------------.
#| .--------------. | .--------------. | .--------------. | .--------------. |
#| |    ______    | | |     ______   | | |   _______    | | |    ______    | |
#| |   / ____ `.  | | |   .' ___  |  | | |  |  ___  |   | | |  .' ____ '.  | |
#| |   `'  __) |  | | |  / .'   \_|  | | |  |_/  / /    | | |  | (____) |  | |
#| |   _  |__ '.  | | |  | |         | | |      / /     | | |  '_.____. |  | |
#| |  | \____) |  | | |  \ `.___.'\  | | |     / /      | | |  | \____| |  | |
#| |   \______.'  | | |   `._____.'  | | |    /_/       | | |   \______,'  | |
#| |              | | |              | | |              | | |              | |
#| '--------------' | '--------------' | '--------------' | '--------------' |
# '----------------' '----------------' '----------------' '----------------'
# .----------------. .----------------. .----------------. .----------------.
#| .--------------. | .--------------. | .--------------. | .--------------. |
#| |    ______    | | |     ____     | | |  _________   | | |      __      | |
#| |  .' ____ '.  | | |   .' __ '.   | | | |_   ___  |  | | |     /  \     | |
#| |  | (____) |  | | |   | (__) |   | | |   | |_  \_|  | | |    / /\ \    | |
#| |  '_.____. |  | | |   .`____'.   | | |   |  _|      | | |   / ____ \   | |
#| |  | \____| |  | | |  | (____) |  | | |  _| |_       | | | _/ /    \ \_ | |
#| |   \______,'  | | |  `.______.'  | | | |_____|      | | ||____|  |____|| |
#| |              | | |              | | |              | | |              | |
#| '--------------' | '--------------' | '--------------' | '--------------' |
# '----------------' '----------------' '----------------' '----------------'
# .----------------. .----------------. .----------------. .----------------.
#| .--------------. | .--------------. | .--------------. | .--------------. |
#| |   _______    | | |   _______    | | |     __       | | |   ______     | |
#| |  |  ___  |   | | |  |  _____|   | | |    /  |      | | |  |_   _ \    | |
#| |  |_/  / /    | | |  | |____     | | |    `| |      | | |    | |_) |   | |
#| |      / /     | | |  '_.____''.  | | |     | |      | | |    |  __'.   | |
#| |     / /      | | |  | \____) |  | | |    _| |_     | | |   _| |__) |  | |
#| |    /_/       | | |   \______.'  | | |   |_____|    | | |  |_______/   | |
#| |              | | |              | | |              | | |              | |
#| '--------------' | '--------------' | '--------------' | '--------------' |
# '----------------' '----------------' '----------------' '----------------'
# .----------------. .----------------. .----------------. .----------------.
#| .--------------. | .--------------. | .--------------. | .--------------. |
#| |  _________   | | |    _____     | | |     __       | | |  ________    | |
#| | |_   ___  |  | | |   / ___ `.   | | |    /  |      | | | |_   ___ `.  | |
#| |   | |_  \_|  | | |  |_/___) |   | | |    `| |      | | |   | |   `. \ | |
#| |   |  _|  _   | | |   .'____.'   | | |     | |      | | |   | |    | | | |
#| |  _| |___/ |  | | |  / /____     | | |    _| |_     | | |  _| |___.' / | |
#| | |_________|  | | |  |_______|   | | |   |_____|    | | | |________.'  | |
#| |              | | |              | | |              | | |              | |
#| '--------------' | '--------------' | '--------------' | '--------------' |
# '----------------' '----------------' '----------------' '----------------'
# .----------------. .----------------. .----------------. .----------------.
#| .--------------. | .--------------. | .--------------. | .--------------. |
#| |     __       | | |    ______    | | |    ______    | | |   _    _     | |
#| |    /  |      | | |   / ____ `.  | | |  .' ____ \   | | |  | |  | |    | |
#| |    `| |      | | |   `'  __) |  | | |  | |____\_|  | | |  | |__| |_   | |
#| |     | |      | | |   _  |__ '.  | | |  | '____`'.  | | |  |____   _|  | |
#| |    _| |_     | | |  | \____) |  | | |  | (____) |  | | |      _| |_   | |
#| |   |_____|    | | |   \______.'  | | |  '.______.'  | | |     |_____|  | |
#| |              | | |              | | |              | | |              | |
#| '--------------' | '--------------' | '--------------' | '--------------' |
# '----------------' '----------------' '----------------' '----------------'
# .----------------. .----------------. .----------------. .----------------.
#| .--------------. | .--------------. | .--------------. | .--------------. |
#| |      __      | | |   _______    | | |     ____     | | |    ______    | |
#| |     /  \     | | |  |  _____|   | | |   .' __ '.   | | |  .' ____ \   | |
#| |    / /\ \    | | |  | |____     | | |   | (__) |   | | |  | |____\_|  | |
#| |   / ____ \   | | |  '_.____''.  | | |   .`____'.   | | |  | '____`'.  | |
#| | _/ /    \ \_ | | |  | \____) |  | | |  | (____) |  | | |  | (____) |  | |
#| ||____|  |____|| | |   \______.'  | | |  `.______.'  | | |  '.______.'  | |
#| |              | | |              | | |              | | |              | |
#| '--------------' | '--------------' | '--------------' | '--------------' |
# '----------------' '----------------' '----------------' '----------------'
# .----------------. .----------------. .----------------.
#| .--------------. | .--------------. | .--------------. |
#| |     ____     | | |     ____     | | |     __       | |
#| |   .'    '.   | | |   .'    '.   | | |    \_ `.     | |
#| |  |  .--.  |  | | |  |  .--.  |  | | |      | |     | |
#| |  | |    | |  | | |  | |    | |  | | |       > >    | |
#| |  |  `--'  |  | | |  |  `--'  |  | | |     _| |     | |
#| |   '.____.'   | | |   '.____.'   | | |    /__.'     | |
#| |              | | |              | | |              | |
#| '--------------' | '--------------' | '--------------' |
# '----------------' '----------------' '----------------'

Transcibe this huge comment and you get the flag: ebCTF{edbdb03c7998fa751be21d1364a58600}. Victory.

bin300 - Crack the password'

Quick look at disassembly reveals it's a binary that loads obfuscated lua script and executes it via luaL_loadbuffer. We can just break there and read the script:
--- moon.gdb ---
b luaL_loadbuffer
set print elements 0
commands 1
call printf("%s\n",$rsi)
end
run
quit
--- end ---
$ gdb -q -nx -x moon.gdb moon
Reading symbols from /tmp/moon...(no debugging symbols found)...done.
Breakpoint 1 at 0x411110
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7ffff7ffa000
warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?

Breakpoint 1, 0x0000000000411110 in luaL_loadbuffer ()
p = 54111037
g = 56321

io.write("Enter your password: ")
io.flush()
password=io.read()
if string.len(password) ~= 32 then
    print("Wrong!")
    return 0
end

v = g
alpha = "0123456789abcdef"
for loop =1,32 do
    v = v * g
    v = v % p
    r = v % 16
    good = string.sub(alpha,r+1,r+1)
    if good ~= string.sub(password,loop,loop) then
        print("Wrong!")
        return 0
    end
end
print("Well done, the flag is: ebCTF{"..password.."}")
-- f02233aca4839124ee6ffa766883c47e

$1 = 488
A debugging session is active.

        Inferior 1 [process 2096] will be killed.

Quit anyway? (y or n) [answered Y; input not from terminal]
My first guess that the comment is the flag paid off - just wrap it with ebCTF{} and submit. Done.

Monday, July 22, 2013

SIGINT CTF 2013: Task fenster (400 pts)



In this task we have a binary - fenster.exe (link to original exe: click), which checks if the given text is our sought flag. The executable is obfuscated and contains some anti-debug. The first step is to remove all garbage and produce a clean exe.
So, let's start!

The first debug check is inside TLS callback at 0x4019CB. All it does is:
encrypt(check_for_debugger, 0x1B, 0xEC, 0x00409CD8);
bool debugger = check_for_debugger();
encrypt(check_for_debugger, 0x1B, 0xEC, 0x00409CD8);
if (debugger) {
   exit(0);
}
encrypt(void* data, int size, int key, int* some_data) is a lengthy function (address: 0x40194B) responsible for data encryption / decryption, but its exact implemenation is not relevant to us. As you can see, we can just remove this TLS callback entry from the executable without any consequence later on.

If we enter the check_for_debugger routine, we can see three further anti-debugging techniques:
push ss
pop ss
This is quite tricky. Any modification of the ss register (excluding the lssinstruction) register causes interrupts to be delayed until the end of execution of next instruction. So, if we step through this code using a debugger (step into/over) the code will "escape" the single-stepping mode immediately after one steps into/over "pop ss". We can safely nop these instructions out.
pushfd
pop eax
This was probably inserted only to fool automatic analyzers and decompilators such as Hex-Rays. We can also nop it out.
call <jmp.&KERNEL32.IsDebuggerPresent>
Standard anti-debugging check, we can replace it with "xor eax,eax" or anything else. Those anti-debugs would often show up inside other functions, so watch out while stepping through the executable. ;)

The main function is located at 0x401EF9. It loads user input from stdin and then does the following with different dataA and dataB pointers in seven iterations (anti-debugging code is skipped, check is a function at 0x00401ab5):
encrypt(check, 0x24, KEY, SOME_PTR);
input_ok &= check(dataA, dataB, user_input);
encrypt(check, 0x24, KEY, SOME_PTR);
To make further analysis easier, we should dump the decrypted check function (and all sub-functions, which are encrypted too) and get rid of all calls to encrypt(). Once this is done, we are ready to dive into the check code and switch from OllyDbg to IDA.

After a brief analysis, it is clear that the function passes our input through finite-state machines (compiled regular expressions). The first subfunction at 0x401C44 performs some kind of initialization, the second one at 0x401C9D executes the machine and the last one at 0x401AD9 checks if the machine completed in a final state. The two pointers passed to check are:
  • int*** dataA - machine specification, dataA[state][letter] is a NULL-terminated list of states that we can reach from the given state after a specific letter. Note that states are numbered from 1 to 255 and dataA[0] refers to the first state. Only capital letters cause transitions. Index=0 corresponds to 'A' and index 25 to 'Z'.
  • int* dataB - a null-terminated list of final state indexes
Once we know the meaning of those structures, we can write some visualization and crack the regular expressions. I wrote a small C++ program which reads data from the "fenster" process, generates a graph description for dot and then compiles it to svg. The results are shown below (rectangles = final states, * = all capital letters, ^XY = all capitals without X and Y):

machine0.svg:

machine1.svg: 

machine2.svg: 

machine3.svg: 

machine4.svg: 

machine5.svg: 

machine6.svg: 

Solving them by hand would be painful (look at machine4.svg!), so the next step was to write an optimized brute-force solver. Analyzing the machines shows that:
  • machine0 - input must end with "EN" and the second letter is "E"
  • machine1 - input is a concatenation of pairs: {"NW", "EN", "ES", "CH", "SW", "RG", "GS", "SE", "RE", "GE", "NE"}
  • machine3 - input length is 16
With the above knowledge, we only have to check around 4*11^6 different inputs. The simplest way for me to check if the input was correct was to just reuse the original check function from fenster.exe loaded as a DLL. The solver's code was as follows:
#include <cstring>
#include <cstdio>
#include <Windows.h>
#include <cassert>

using namespace std;

int machines[7] =   { 0x4077A0, 0x407E40, 0x4082E0, 0x408BA0, 0x4098C0, 0x409B48, 0x409C68 };
int end_states[7] = { 0x4077DC, 0x407E70, 0x408300, 0x408BE4, 0x409920, 0x409B58, 0x409C70 };
const int pairscnt = 11;
char* pairs[pairscnt] = {"NW", "EN", "ES", "CH", "SW", "RG", "GS", "SE", "RE", "GE", "NE"};
char key[17] = " E            EN";
int it[7] = {7};
int regex_match, memset_addr;

__declspec(naked) bool __cdecl check()
{
    __asm
    {
        push edi
        push ebp
        mov ebp, esp
        and esp, 0xFFFFFFF0

        mov edi, 0

        looop:
            sub esp,4
            push offset key
            push end_states[edi*4]
            push machines[edi*4]
            call regex_match
            add esp, 0x10
            test eax,eax
            jz hop

            inc edi
            cmp edi, 7
        jnz looop

hop:
        mov esp, ebp
        pop ebp
        pop edi
        retn
    }
}

int main()
{
    int fenster = (int)LoadLibraryA("~fenster2.dll");

    // It doesn't work on bases different from 0x400000,
    // because the binary has no relocations (e.g. final states list pointers)
    // just run it until it works
    assert(fenster == 0x400000);
    regex_match = 0x401d97;
    memset_addr = 0x40C17C;

    // Resolving imports
    *(int*)memset_addr = (int)memset;

    // Assert that last pair is set
    assert(strlen(key) == 16);

    while(it[6] < pairscnt)
    {
        for(int i=0; i<7; i++)
           key[i*2] = pairs[it[i]][0],
           key[i*2+1] = pairs[it[i]][1];
 
        if(check())
            puts(key);
 
        it[0]++;
        for(int i=0; i<6 && it[i]==pairscnt; i++)
            it[i+1]++,
            it[i] = 0;
    }
    return 0;
}
where ~fenster2.dll is a deobfuscated executable, you can download it here: https://docs.google.com/file/d/0B-L9DIAuaV7STkNjNGdBY1RnQ2M/edit?usp=sharing. After running the application for a short while, it spit out the "REGENECHENSESWEN" textual string, which indeed turned out to be the correct flag. +400pts :)