Reverse Engineering

Challenge
Link

Paranoia (100 pts)

Grip (100 pts)

Sperm Rev (100 pts)

Risks (205 pts)

Packeta (460 pts)

Mips (477 pts)

Orgalorg (498 pts)

Paranoia (100 pts)

Description

im baby

Author: miyako

nc 20.80.240.190 1234

Solution

Given ELF 64 bit file, open it using IDA.

int __fastcall main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // eax
  int v4; // ebx
  int v5; // eax
  unsigned __int64 i; // [rsp+8h] [rbp-18h]

  v3 = time(0LL);
  srand(v3);
  for ( i = 0LL; i <= 0x11; ++i )
  {
    v4 = flag[i];
    v5 = rand();
    printf("%i ", v4 ^ ((unsigned __int8)(((unsigned int)(v5 >> 31) >> 24) + v5) - ((unsigned int)(v5 >> 31) >> 24)));
  }
  putchar(10);
  return 0;

Basically it just do xor with random value with seed current time (time(0)). To get the plaintext we can do the same process. To overcome delay issue, we can do little bruteforce from current time.

Flag: akasec{n0t_t00_m4ny_br41nc3lls_l3ft}

Grip (100 pts)

Description

its...its...Grippy

Author: miyako

Solution

Given ELF 64 bit, open it using IDA.

We can see that there is mmap function called then the address from mmap (v14) used to store value of static value xored with 0xf2. At the end, v14 called in the main function. From those information we can assume that value on address v14 contains valid assembly because it called in the end. So dump the bytecode then open it again using decompiler.

3 null bytes at the end will cause error on decompile process, so put 0xc3 (ret) to overcome the issue.

Now we have the code, then just convert it to python and get the flag.

Flag: akasec{sh1tty_p4ck3d_b1n4ry}

Sperm Rev (100 pts)

Description

before baby rev, there was sperm rev <3

solve it fast to win another race in your life.

Author: Pengolian

Solution

Given ELF 64 bit, open it using IDA. Nothing useful in available function, check on strings.

Flag: AKASEC{strings_b35t_t00l_1n_r3v3r5e_eng1n33r1ng}

Risks (205 pts)

Description

theres this pretty cool isa called riscv it sounds awesome.

Author: miyako

Solution

Given ELF 64 bit RISCV file, open it using ghidra. Rename some known function to make it easily to understand.

So there are 5 custom functions in the program.

  • FUN_00101ad4, FUN_00101346, FUN_00100c8c, and FUN_00100786 process our input with some operation such as xor and add.

  • compare_value validate our processed input with static value

From those informations we can get the valid input by utilizing z3. Below is my solution

Flag: akasec{1n_my_b4g_0n3_s3c0nd_0n3}

Packeta (460 pts)

Description

BalanΓ§a o ombrin', vai, vai BalanΓ§a o ombrin', vai, vai

BalanΓ§a o ombrin' Jogadinha do Packeta

Author: Pengolian

Solution

Given 2 ELF 64 bit files which are flag and packeta. First, open packeta using IDA. There are many function in the program, rename each function.

  • generate_key function

So basically it generate key based on (current time % 500) + 4919. From that information we know that the possibility of the key only 500 (possible to brute).

  • call_rc4 function

Lets take a look on rc4 function

From above code we can confirm that byte_5020 used as the key for rc4 function. To know the ciphertext values we can debug the executable using GDB.

The ciphertext values start with 0x4d75. Check on flag binary to findout on which section those ciphertext.

From image above we can confirm that the ciphertext section is on .text section. To get the valid key we can do bruteforce and validate manually which plaintext consist of valid assembly instruciton because the first ciphertext is the start function. Below is my script

For the comparison we can use the standard start function, such as from packeta file.

So i == 127 looks like the correct value because it result valid assembly like standard start function. To get the rest plaintext we can debug the program and set the value for the (current_time % 500).

Continue the process then run the new generated ELF named new.

Flag: AKASEC{h4lf_p4ck_h4lf_7h3_fl46}

Mips (477 pts)

Description

check out my 16 star pb (note: you need ares to run the rom properly)

Author: miyako

nc 20.80.240.190 4321

Solution

Given Nintendo 64 ROM image. During the competition i found good referencearrow-up-right about nintedo 64 reverse engineering. From the description we know that we can run the rom using aresarrow-up-right. In this case i install the emulator on ubuntu. To load the rom we can click Load -> Nintendo -> Nintendo 64.

Setup the input mapping by click Settings -> Input.

Press some random button and it will reflected on screen, to submit the button we can press enter button (start).

Next, we need to decompile the rom. I use ghidra with N64LoaderWVarrow-up-right plugin to do that.

Searching for "wrong" string then we will found the validation program.

From above code we got some information

  • Line 30: Our input mapped to some constant value

  • Line 33: Input length is 0x1e, we can also confirm through user interface by input more than 30 button then it will reset

  • Line 34: Our mapped input validated with constant value at (DAT_800270c8)

Now we need to get the valid input mapping, one of the way to do that is by debugging. Click Settings -> Debug then enable debugging with below options.

After that, use gdb-multiarch to connect to gdb server.

Then breakpoint at 0x8000b53c.

Press up button (for example), then the breakpoint will be hitten. Look at v0 register to know the mapped value for up button.

Do the same thing until got all mapped input then create script to get the reflected input on screen.

Flag: akasec{m1ps_1s_c00l_l0l}

Orgalorg (498 pts)

Description

Did you know that Gunter is literally Orgalorg, a primordial cosmic entity, feared as the Breaker of Worlds, disguised as a penguin on earth...

nc 20.80.240.190 1235

Author: pengolian

Solution

Given ELF 64 bit file, open it using IDA.

So in main function there are two user defined function which are func_1 and sub_5950. Lets take a look on func_1. At the time of competition i've renamed some function while debugging.

  • anti_debug_1

    • anti debug function, will exit the process if debugging detected

    • will open /proc/self/status to check debugging status

    • We can easily bypass the the anti debug by changing the return value

  • get_string

    • kind of string obfuscation, the function will return "plaintext" of obfuscated/encrypted string

  • sub_bbc0

    • check length of OGP and ensure that it constructed only from digits

  • prctl

    • set the process name to sleep

  • dword_17240

    • There will be set of dword_17240 variable to 1 if there is valid OGP and debugging not detected

Back to main function, after calling of func_1 there will be validation of dword_17240. If dword_17240 not zero it will call func_2. So lets take a look on func_2.

  • fork

    • There is call of fork, so after calling fork the rest flow will be processed by the child process

    • Set follow fork mode to child on GDB to debug the child process

Next, take a look on func_3

  • Line 50: initialize socket listening, bind to port 50009

  • Line 121: sending banner (during the initial connection)

  • Line 126: process our input

Next lets take a look on process_recv.

  • Line 235: receive user input

  • Line 318: process received user input

Take a look on sus_func_1

  • Line 84: compare "p455" with first value on splitted input

  • Line 91-94: compare second value on splitted input with some character and hash

    • all the hash are available on online database because it only a few character

    • sub_DEB0 == md5

So basically we can find all the valid values by set breakpoint on all cmp instruction. For example

During the competition i create gdb script to automate the repetitive task.

After get the valid input, just send it to the server and got the shell

Flag: AKASEC{Orgalor6_1n_d1sgu1s3_as_d4em0n_p3ngu1n}

Last updated