picoCTF2019 Reverse Engineering Asm

Hello, here’s my take on the picoCTF2019 reverse engineering asm challenges. If you don’t know assembly, please watch a few tutorials on it:

asm1 – Points: 200

CMP: Compares the first source operand with the second source operand and sets the status flags in the EFLAGS register according to the results. The comparison is performed by subtracting the second operand from the first operand and then setting the status flags in the same manner as the SUB instruction. When an immediate value is used as an operand, it is sign-extended to the length of the first operand.

JG: Jump short if greater (ZF=0 and SF=OF)

JNE: Jump short if not equal (ZF=0)

asm1:
	<+0>:	push   ebp # 
	<+1>:	mov    ebp,esp # 
	<+3>:	cmp    DWORD PTR [ebp+0x8],0x37a # 0x345 - 0x37a = -0x35

	<+10>:	jg     0x512 <asm1+37> # -0x35 is greater than 0x512 because it overflowed.
	<+12>:	cmp    DWORD PTR [ebp+0x8],0x345
	<+19>:	jne    0x50a <asm1+29>
	<+21>:	mov    eax,DWORD PTR [ebp+0x8]
	<+24>:	add    eax,0x3
	<+27>:	jmp    0x529 <asm1+60>
	<+29>:	mov    eax,DWORD PTR [ebp+0x8]
	<+32>:	sub    eax,0x3
	<+35>:	jmp    0x529 <asm1+60>

	<+37>:	cmp    DWORD PTR [ebp+0x8],0x5ff # 0x345 - 0x5ff = -0x2BA
	<+44>:	jne    0x523 <asm1+54> # -0x2BA is not equal to 0x523
	<+46>:	mov    eax,DWORD PTR [ebp+0x8]
	<+49>:	sub    eax,0x3
	<+52>:	jmp    0x529 <asm1+60>
	<+54>:	mov    eax,DWORD PTR [ebp+0x8] # eax = 0x348
	<+57>:	add    eax,0x3 # eax = eax + 3
	<+60>:	pop    ebp 
	<+61>:	ret    # return eax

Next Levels

The next levels asm2, asm3 and asm4 got a little more complex and solving them was starting to feel like a chore, my mind was hurting and I didn’t want to keep going the manual way. Lucky, I found noahc3 and this writeup I managed to solve them easily.

We’re going to modify the assembly and compile it with GCC, on my 64 bit Ubuntu I had to install the gcc-multilib package in order to compile 32 bit executables.

Here’s the modified code for the asm3 task:

.intel_syntax noprefix

.global asm3

asm3:
	push   ebp
	mov    ebp,esp
	xor    eax,eax
	mov    ah,BYTE PTR [ebp+0x8]
	shl    ax,0x10
	sub    al,BYTE PTR [ebp+0xe]
	add    ah,BYTE PTR [ebp+0xc]
	xor    ax,WORD PTR [ebp+0x10]
	nop
	pop    ebp
	ret    

What we’re going to do next is to write a simple main.c program that calls the functions with the required arguments:

#include <stdio.h>

int main(void) {
    printf("Hello World!");
    // printf("Flag: %un", asm2(0xe,0x22));
    printf("Flag: %un", asm3(0xcdc485c1,0xd6bd5e88,0xe4c1548d));
    // printf("Flag: %un", asm4("picoCTF_fdb55"));
}

Next we’re going to compile the assembly code, the main.c file and the final executable:

 gcc -m32 -c asm3.S -o asm3.o -fno-stack-protector -no-pie
 gcc -m32 -c main.c -o main.o -fno-stack-protector -no-pie
 gcc -m32 -o a.out main.o asm3.o -fno-stack-protector -no-pie

If we execute a.out we should get our flag.

Thanks for reading!

picoCTF 2019 Reverse Engineering Vault Doors

I’m always late to the party but here’s my solutions to the PicoCTF2019 Vault Doors challenges from the reverse engineering section. I did it this mainly to improve my skills and hopefully to learn some new things.

vault-door-training – Points: 50

Your mission is to enter Dr. Evil’s laboratory and retrieve the blueprints for his Doomsday Project. The laboratory is protected by a series of locked vault doors. Each door is controlled by a computer and requires a password to open. Unfortunately, our undercover agents have not been able to obtain the secret passwords for the vault doors, but one of our junior agents obtained the source code for each vault’s computer! You will need to read the source code for each level to figure out what the password is for that vault door. As a warmup, we have created a replica vault in our training facility. The source code for the training vault is here: VaultDoorTraining.java

The password is in the source code. You can copy/paste it and put it in the picoCTF{flag} format.

    public boolean checkPassword(String password) {
        return password.equals("w4rm1ng_Up_w1tH_jAv4_3b500738c12");
    }

vault-door-1 – Points: 100

The second challenge is the same as the first one but you’ll have to re-order the array. Associate each character comparison with the array index and you’ll get something like:

d35cr4mbl3_tH3_cH4r4cT3r5_03f841

vault-door-3 – Points: 200

The third challenge uses loops and array in order to construct the password, we can solve it by feeding it some dummy data and see how it modifies it:

        String s = new String(buffer);
        System.out.print("s: " + s);
        //in  jU5t_a_s01234567 89abcdefghijklmn
        //ou: jU5t_a_s76543210 m9kbidgfehcjal8n
        //    jU5t_a_sna_3lpm1 3gc49_u_4_m0rf41 
        //s:  jU5t_a_s1mpl3_an4gr4m_4_u_90cf31
        return s.equals("jU5t_a_sna_3lpm13gc49_u_4_m0rf41");
    }

    public static void main(String[] args) {
        boolean result = checkPassword("jU5t_a_s0123456789abcdefghijklmn");
        System.out.print("nDone: " + result);
    }

vault-door-4 – Points: 250

The 4th vault door challenge is even easier, all you need to do is convert numbers from different bases back to ASCII characters. Use online number converters.

        byte[] myBytes = {
            106 , 85  , 53  , 116 , 95  , 52  , 95  , 98  , // ascii: jU5t_4_b
            0x55, 0x6e, 0x43, 0x68, 0x5f, 0x30, 0x66, 0x5f, // hex: UnCh_0f_
            0142, 0131, 0164, 063 , 0163, 0137, 063 , 0141, // octal: bYt3s_3a
            '7' , '2' , '4' , 'c' , '8' , 'f' , '9' , '2' , // characters: 724c8f92
            // jU5t_4_bUnCh_0f_bYt3s_3a724c8f92
        };

vault-door-5 – Points: 300

This challenge has the password URL Encoded then Base64 Encode, to solve it you just decode it. You can do it using CyberChef.

    public boolean checkPassword(String password) {
        String urlEncoded = urlEncode(password.getBytes());
        String base64Encoded = base64Encode(urlEncoded.getBytes());
        String expected = "JTYzJTMwJTZlJTc2JTMzJTcyJTc0JTMxJTZlJTY3JTVm"
                        + "JTY2JTcyJTMwJTZkJTVmJTYyJTYxJTM1JTY1JTVmJTM2"
                        + "JTM0JTVmJTMxJTMxJTM3JTM3JTY2JTM3JTM4JTMz";
        return base64Encoded.equals(expected);
    }

vault-door-6 – Points: 350

This challenge uses a XOR encryption scheme, we can defeat it using CyberChef or modify the code and run it to spit out the password:

    public void checkPassword() {
        byte[] myBytes = {
            0x3b, 0x65, 0x21, 0xa , 0x38, 0x0 , 0x36, 0x1d,
            0xa , 0x3d, 0x61, 0x27, 0x11, 0x66, 0x27, 0xa ,
            0x21, 0x1d, 0x61, 0x3b, 0xa , 0x2d, 0x65, 0x27,
            0xa , 0x60, 0x62, 0x36, 0x67, 0x6d, 0x6c, 0x67,
        };
        for (int i=0; i<32; i++) {
            System.out.print( (char) (myBytes[i] ^ 0x55) );
        }
    }

vault-door-7 – Points: 400

To solve this challenge I’ve used this Binary to Decimal converter to grab the hex values then I used CyberChef to convert them back into ASCII.

vault-door-8 – Points: 450

The final challenge can be solved by reversing the steps of the scramble function, everything else remains unchanged. We then run it by feeding the expected bytes to the modified scramble function.

 public char[] scramble(String i) {
  /* Scramble a password by transposing pairs of bits. */
  char[] a = i.toCharArray();
  for (int b = 0; b < a.length; b++) {
   char c = a[b];
   c = switchBits(c, 6, 7);
   c = switchBits(c, 2, 5);
   c = switchBits(c, 3, 4);
   c = switchBits(c, 0, 1);
   c = switchBits(c, 4, 7);
   c = switchBits(c, 5, 6);
   c = switchBits(c, 0, 3);
   c = switchBits(c, 1, 2);
   a[b] = c;
  }
  return a;
 }
// You'll need to pass the expected array to the scramble function for unscrambling:
  System.out.println("Expected " + String.valueOf(expected));
  System.out.println("Scrambled " + String.valueOf(scramble(String.valueOf(expected))));

That’s all! Hope you liked it.

Bypassing ptrace calls with LD_PRELOAD on Linux

Hello,

Here’s a quick article on how to bypass calls to ptrace when debugging a Linux executable.

By calling ptrace with the PTRACE_TRACEME option, a process can detect if it’s being debugged and execute different instructions. This an effective anti-debugging technique.

For example, take the following C program:

#include <stdio.h>
#include <sys/ptrace.h>

int main() {
    if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
      printf("I'm being debugged!n");
    } else {
      printf("Normal flown");
    }
    return 0;
}

If we execute the program from above we get Normal flow on our screen but if we debug it with gdb we get Err: I'm being debugged!

root@kali:~/Downloads# strace ./a.out 
...
munmap(0x7fb7c945e000, 90919)           = 0
ptrace(PTRACE_TRACEME)                  = -1 EPERM (Operation not permitted)
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
brk(NULL)                               = 0x55c2d37e6000
brk(0x55c2d3807000)                     = 0x55c2d3807000
write(1, "Err: I'm being debugged!n", 25Err: I'm being debugged!
) = 25
exit_group(0)                           = ?
+++ exited with 0 +++

To bypass this, we can use the LD_PRELOAD environment variable. It lets us control the loading path of a shared library, which allows us to stub out library functions such as ptrace.

We can create the following file:

long ptrace(int request, int pid, void *addr, void *data) {
    return 0;
}

And compile it as a shared library with the following command:

gcc -shared ptrace.c -o ptrace.so

Next, we can set the environment variable LD_PRELOAD using the following commands:

  • in the shell: export LD_PRELOAD=./ptrace.so
  • in gdb: set environment LD_PRELOAD=./ptrace.so

Demo:

gdb-peda$ file a.out 
Reading symbols from a.out...
(No debugging symbols found in a.out)
gdb-peda$ r
Starting program: /root/Downloads/a.out 
Err: I'm being debugged!
[Inferior 1 (process 1939) exited normally]
Warning: not running
gdb-peda$ set environment LD_PRELOAD=./ptrace.so
gdb-peda$ r
Starting program: /root/Downloads/a.out 
Normal flow
[Inferior 1 (process 1946) exited normally]
Warning: not running
gdb-peda$ 

Thanks for reading!

Root-Me: GB – Basic GameBoy crackme walkthrough

Hello,

In this article I will describe how I solved the GB – Basic GameBoy crackme challenge from Root-Me.

Before reading this article you should attempt to solve the challenge on your own. Start by reading/skimming through the GameBoy CPU manual then download an emulator such as mGba and play with the ROM. To disassemble the ROM I’ve used Ghidra and mgbdis.


After reading through the GameBoy CPU manual, I’ve opened the file in Ghidra and found these interesting strings:

If you emulate the ROM using mGba and press the Left key then the Enter key, the message “Left” will appear on the screen, for the moment I can assume that the strings are related to the message.

Ghidra doesn’t know about the GameBoy ROM structure and I don’t know either, so I’ve tried to disassemble the ROM with the help of a specialized GameBoy disassembler:

➜  mgbdis git:(master) ✗ ./mgbdis.py crack_rom.gb 
Loading "crack_rom.gb"...
ROM MD5 hash: 51ff0d38b93107c38a753d9b0ee1576c
Generating labels...
Generating disassembly..
Disassembly generated in "/home/denis/Downloads/mgbdis/disassembly"

By opening the output of the disassembler and searching for 0459 (the address of the Nope string) I’ve found code that references it at 0415.

I went back to Ghidra and disassembled the block at 0415 by pressing the D key.

This seems to be the block that checks some values from RAM and prints the flag if the values are correct.

The first comparison is done for the Left key. It loads the value from the RAM address 0xc0b0 into the A register.

The A register is then compared to 0x32 and there’s a conditional jump to the NopeBlock. JP NZ,NN ;jumps if Z is reset

                             LAB_ram_03c0                   
        ram:03c0 11 b0 c0        LD         DE,0xc0b0
        ram:03c3 1a              LD         A,(DE=>DAT_ram_c0b0)
        ram:03c4 4f              LD         C,A
        ram:03c5 fe 32           CP         0x32
        ram:03c7 c2 15 04        JP         NZ,NopeBlock
        ram:03ca 18 03           JR         LAB_ram_03cf
        ram:03cc c3 15 04        JP         NopeBlock

CP is a subtraction from A that doesn't update A, only the flags it would have set/reset if it really was subtracted. If A == N, then Z flag is set.

So if A = 0x32 then Z is set and the jump to NopeBlock only happens if Z is reset. Sounds easy to me. To pass the check the value at 0xc0b0 needs to be 0x32.

If we look at the memory view in the mGba emulator, the location at 0xc0b0 has the value 0x39. If we press the Left key the value is decremented.

To get the flag you must solve for the Up, Down and Right keys.

Thanks for reading! ❤