Defcon 23 CTF Quals 2015 – Babycmd writeup

The babycmd challenge was an x64 ELF binary supporting 4 commands: ping, dig, host, and exit. In the case of ping, dig and host, it just calls the corresponding binary with a user-controlled argument.

This binary uses signal(2) 0xE (SIGALRM – Timer signal from alarm(2)) and alarm() in order to terminate the process after 45 seconds. This was a bit annoying while working on this binary, so I replaced the original argument 0x2d for alert() with a 0; as explained in the alarm(2) documentation, if the seconds argument is 0, no new alarm is scheduled.

Original code:

.text:0000000000001267                 mov     edi, 0Eh
.text:000000000000126C                 call    _signal
.text:0000000000001271                 mov     edi, 0x2d
.text:0000000000001276                 call    _alarm

Patched code:

.text:0000000000001267                 mov     edi, 0Eh
.text:000000000000126C                 call    _signal
.text:0000000000001271                 mov     edi, 0
.text:0000000000001276                 call    _alarm

For all the supported commands, this program does some basic validation of the user-provided argument before calling the corresponding binary. This filter is a kind of blacklist which rejects user input if it contains characters like “&”, “;” and “|”, which may be abused to inject OS commands. You should note that this function also removes spaces (char 0x20) from the user input.

validate_input

Continue reading

ForbiddenBITS CTF 2013 – Poir 150 Write up

We were provided with a pcap capture. The capture has mostly HTTP traffic, which seems to be the transfer of a file named key.7z. The HTTP client, which is Python’s urllib, requests the file in very small chunks, using the “Range: bytes=xx-yy” header.

To make things more complicated, the HTTP client requests the byte ranges without any particular order, and it also requests overlapping ranges. These details make it harder to extract the key.7z file from the pcap capture.

request-range

So I applied the following filter in Wireshark, in order to show just the HTTP responses from the server:

http && ip.src == 211.54.171.67

Continue reading

ForbiddenBITS CTF 2013 – Old 50 Write up

We were provided with a bin.bin file, which size is 512 bytes. Doing $ file bin.bin shows us that the file is a boot sector.

In order to run the boot sector I’ve followed an article from the developers of MikeOS (Note that I’ve linked to the Google Cache copy since the original site appears to be down).

So I downloaded a floppy disk image, renamed it to floppy.flp, and then I copied the boot sector of this challenge to the floppy disk image:

$ dd status=noxfer conv=notrunc if=bin.bin of=floppy.flp

Then I started QEMU using the floppy disk image containing the CTF boot sector:

$ qemu-system-i386 -fda floppy.img

QEMU boots from our floppy disk image, and the boot sector asks for a password:

boot-sector
Continue reading

Nullcon HackIM CTF 2013 – Reverse Engineering 300 Write up

Reverse Engineering 300

This Reverse Engineering challenge was a virtual machine implemented in Javascript:

/*
	+---------------------------+
	| Custom Javascript Crackme |
	+---------------------------+

[+] Tested on : Safari, Google-Chrome, Opera, Firefox. (IE ?? O..puhleez!)
[+] No obfuscation, nothing. Just plain code. 🙂
[?] Should be an easy one, eh? 😉
[+] Best of luck!
(c) HackIM2013

*/

var key=[];
var code=[901, 340, 505, 140, 305, 461, 901, 722, 340, 539, 723, 241, 339, 540, 238, 142, 342, 901, 722, 901, 722, 606, 000, 542, 243, 243, 244, 340, 830, 653, 553, 140, 145, 353, 546, 140, 653, 000, 17, 10, 000, 001, 000, 400, 60, 459, 41, 22, 76, 76, 75, 75, 37, 417, 560, 140, 145, 360, 547, 140, 417, 567, 140, 145, 367, 548, 140, 417, 574, 140, 145, 374, 549, 140, 417, 581, 140, 145, 381, 550, 140, 417, 588, 140, 145, 388, 551, 140, 417, 595, 140, 145, 395, 552, 140, 417, 423];
var output=[];

function msg()
{
var message=output.toString().replace(/\,/gi,"");;
document.getElementById("key").value=message;
}

function LMC()
{
	var accumulator=0;
	var inp_counter=0;
	var code_counter=0;
	var pc=code[code_counter];
	while(code[code_counter]>0)
	{
		pc=code[code_counter];
		var mailbox=parseInt(pc%100);
		var opcode=parseInt(pc/100);
		switch(opcode)
		{
			case 1:
  						accumulator=accumulator+code[mailbox];
  						code_counter++;
  						break;
			case 2:
  						accumulator=accumulator-code[mailbox];
  						code_counter++;
  						break;
			case 3:
  						code[mailbox]=accumulator;
  						code_counter++;
  						break;
			case 5:
  						accumulator=code[mailbox];
  						code_counter++;
  						break;
			case 6:
  						code_counter=mailbox;
  						break;
			case 7:
  						if(accumulator==0)
  							{code_counter=mailbox;}
  						else{code_counter++;}
  						break;
			case 8:
  						if(accumulator>=0)
  							{code_counter=mailbox;}
  						else{code_counter++;}
  						break;
			case 9:
  						if(pc==901)
  						{
  							if(inp_counter<key.length)
  							{
  								accumulator=key[inp_counter];
  							 	inp_counter++;
  							 }
  							 else
  							 {
  							 	accumulator=0;
  							 }
  						}
  						else if(pc== 902)
  						{
  							output.push(String.fromCharCode(accumulator));
   						}
  						code_counter++;
  						break;
  		case 0:
  						code[0]=0;
  						code_counter=0;
  						break;
    	default:
  						code[0]=0;
              code_counter=0;
              break;
		}
	}
}

function setup()
{
	 var temp=document.getElementById("key").value;
	 for(var i=0; i<temp.length; ++i)
	 {
	 	key.push(temp.charCodeAt(i));
	 }
	 LMC();
	 msg();
}

Let’s dissect this virtual machine!

Continue reading

Nullcon HackIM CTF 2013 – Reverse Engineering 100 Write up

Reverse Engineering 100

We were provided with this highly obfuscated code:

''=~('('.'?'.'{'.('`'|'%').('['^'-').('`'|'!').('`'|',').'"'.('['^'.').('['^'(').('`'|'%').('{'^'[')
.('['^'(').('['^'/').('['^')').('`'|')').('`'|'#').('['^'/').';'.('['^'.').('['^'(').('`'|'%').('{'^
'[').('['^',').('`'|'!').('['^')').('`'|'.').('`'|')').('`'|'.').('`'|"'").('['^'(').';'.('`'|')').(
'`'|'&').'('.'\\'.'$'.'#'.('`'^'!').('{'^')').('`'^"'").('{'^'-').'='.'='.('^'^('`'|','))."\)".'\\'.
'{'.('`'|')').('`'|'&').'('.'\\'.'$'.('`'^'!').('{'^')').('`'^"'").('{'^'-').'['.('^'^('`'|'.')).']'
.'.'.'\\'.'$'.('`'^'!').('{'^')').('`'^"'").('{'^'-').'['.('^'^('`'|'/')).']'.('`'|'%').('['^('*')).
'\\'.'$'.('`'^'%').('`'^'.').('{'^'-').'\\'.'{'."'".('{'^'.').('{'^'(').('`'^'%').('{'^')')."'".'\\'
.'}'.')'.'\\'.'{'.('['^'+').('['^')').('`'|')').('`'|'.').('['^'/').'\\'.'"'.('`'^'&').('`'|(',')).(
'`'|'!').('`'|"'").'='."'".('`'^"'").('`'|'/').('`'|',').('`'|'$').('`'|'%').('`'|'.').('`'^('$')).(
'`'|'!').('['^'"').('['^'(').('`'^'!').('['^')').('`'|'%').('`'^'"').('`'|'!').('`'|'#').('`'|"\+").
"'".'\\'.'"'.'\\'.'}'.'\\'.'}'.'"'.'}'.')');$:='.'^'~';$~='@'|'(';$^=')'^'[';$/='`'|'.';$,='('^"\}";

It looks like a lot of XOR and OR logical operations between characters, plus a bunch of concatenations of strings.
This is probably Perl or PHP code, and since I’m not fluent in any of them I decided to translate it to Python code to better understand it.
Continue reading