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)

	<+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

	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]
	pop    ebp

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:


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.