CodeGate 2012 Quals bin400 writeup

February 28, 2012 by admin · Leave a Comment 

Thanks to Deroko and some ARTeam members to play with CLGT. Below is the write up by Deroko posted on http://www.xchg.info/wiki/index.php?title=CodeGate2012_bin400

CodeGate2012 bin400

Challenge: The Rewolf in Kaspersky
Link to challenge : http://deroko.phearless.org/codegate2012/bin/bin400.zip

So Rewolf vm, is packed with something called KasperSky according toProtectionID (never heard of this packer ). Unpacking is trivial, like with any simple packer. Run to OEP, dump, fix imports:

Here is OEP for ReWolf VM:

Rewolf oep.png

And here is OEP for original program (note you need to dump at ReWolf VM, but importrec will work only properly if you use this OEP) :

Real oep.png

Once we have file dumped, we might run it to get idea how it actually looks like:

Appwindow.png

Not much there :( 1st time I pressed some key while program was focused I got an exception:

Exception.png
Exception code.png

At first I thought that my dump is broken, so I tried with original application, same thing happened. Hmmm so this is common problem, but challenge is definitely not broken, so we need to see what’s going on, and trace instruction per instruction in ReWolf VM.

After a little bit of tracing I noticed that exception comes after virtualized jcc is executed, because next instruction size is wrong. (From exception you can see thatecx is quite big number which it should not be):

0041D000   50               PUSH EAX            <----- start of jcc opcode
0041D001   9C               PUSHFD
0041D002   58               POP EAX
0041D003   53               PUSH EBX
0041D004   E8 00000000      CALL test.0041D009
0041D009   5B               POP EBX
0041D00A   8D5453 08        LEA EDX,DWORD PTR DS:[EBX+EDX*2+8]
0041D00E   5B               POP EBX
0041D00F   FFE2             JMP EDX

If jcc is taked edx is set to 1, otherwise edx is 0.

0041D0DE   33D2             XOR EDX,EDX                              ; test.0041D023
0041D0E0   EB 04            JMP SHORT test.0041D0E6
0041D0E2   33D2             XOR EDX,EDX
0041D0E4   EB 01            JMP SHORT test.0041D0E7
0041D0E6   42               INC EDX
0041D0E7   50               PUSH EAX
0041D0E8   9D               POPFD
0041D0E9   58               POP EAX
0041D4AA   5A               POP EDX                <---- pop EIP (jcc not taken)
0041D4AB   58               POP EAX
0041D4AC  ^E9 2CFFFFFF      JMP test.0041D3DD
0041D4B1   0FB657 03        MOVZX EDX,BYTE PTR DS:[EDI+3]
0041D4B5   FF7424 08        PUSH DWORD PTR SS:[ESP+8]
0041D4B9   9D               POPFD
0041D4BA   E8 41FBFFFF      CALL test.0041D000
0041D4BF   85D2             TEST EDX,EDX
0041D4C1  ^74 E7            JE SHORT test.0041D4AA
0041D4C3   5A               POP EDX
0041D4C4   0357 04          ADD EDX,DWORD PTR DS:[EDI+4] <--- increment EIP (jcc taken)
0041D4C7   034F 04          ADD ECX,DWORD PTR DS:[EDI+4]
0041D4CA   58               POP EAX
0041D4CB  ^E9 5AFEFFFF      JMP test.0041D32A

[edi+4] = 00000104

0041D32A   8BF2             MOV ESI,EDX
0041D32C   46               INC ESI
0041D32D   8A02             MOV AL,BYTE PTR DS:[EDX]           <--- size of next instruction
0041D32F   3242 01          XOR AL,BYTE PTR DS:[EDX+1]         <--- xor 1st 2 bytes to get proper sie
0041D332   0FB6C0           MOVZX EAX,AL
0041D335   50               PUSH EAX                           <--- size of instruction passed to memcpy
0041D336   56               PUSH ESI
0041D337   57               PUSH EDI
0041D338   E8 D8050000      CALL test.0041D915                 <--- memcpy

BOOM Exception

0041DB10  25 93 97 B6 C4 C5 89 8A                          %“—¶ÄʼnŠ

Instruction size is calculated as 25 ^ 93 = B6 which is wrong for instruction size in this case.

At this point I decided to try and patch jcc vm handler so jcc will not be taken:

Patch.png

and then I typed something:

Firstcharacter.png

And then I just kept pressing keys:

Okunlocked.png

Press OK and you get the key:

Finalkey.png

So correct key for bin400 is : WonderFul_lollol_!

Greetings

I would like to say tnx to my ARTeam mates, vnsecurity guys, and of coursesuperkhung for listening to my random blabing on skype during CTF :)

Author

deroko of ARTeam


Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

CodeGate 2012 Quals bin500 writeup

February 28, 2012 by admin · Leave a Comment 

Thanks to Deroko and some ARTeam members to play with CLGT. Below is the write up by Deroko posted on http://www.xchg.info/wiki/index.php?title=CodeGate2012_bin500

CodeGate2012 bin500

Challenge: Seeing that it is not all.
Link to challenge: http://deroko.phearless.org/codegate2012/bin/bin500.zip

This binary is double ReWolf vm, and python script for modified Olly by Immunity.

Script which comes with binary uses marshal.loads to load already compiled pyc code which was produced with marshal.dump

To get .pyc back we need to make some modification to our script:

Modifiedscript.png

Now C:\test.pyc will have dump of python bytecode.

If you look carefully through script, some strings might look like a clue:

readMemory
getRegs
EIP
Nice work, Key1 :
But, Find Next Key!
Nice work, Key2 :
Input Key : Key1 + Key2
Nothing Found ...

So this script will probably try to read from current EIP some bytes (readMemory + EIP are good hint), and make key out of it. After modifying test.pyc to have proper layout:

00000000  03 f3 0d 0a dc dd e2 4c  63 00 00 00 00 00 00 00  |.......Lc.......|
00000010  00 02 00 00 00 40 00 00  00 73 22 00 00 00 64 00  |.....@...s"...d.|
00000020  00 64 01 00 6c 00 00 5a  00 00 64 02 00 84 00 00  |.d..l..Z..d.....|

Which is actually 4 bytes for python signature4 bytes for timestamp +marshal.dump() data we get .pyc file which we can decompile.

For sake of this solution, we will use some simple program to dump python byte-code, and one I found here:http://nedbatchelder.com/blog/200804/the_structure_of_pyc_files.html

After disassembling binary with this python script we get (I cut not important parts):

             15 LOAD_ATTR                2 (readMemory)
             18 LOAD_CONST               1 (4237456)
             21 LOAD_CONST               2 (80)
             24 CALL_FUNCTION            2

So from address 40A890 it will read 80 bytes and keep it in internal buffer.

Now comes interesting part when it actually gets keys:

 19          54 LOAD_FAST                4 (regs)
             57 LOAD_CONST               3 ('EIP')
             60 BINARY_SUBSCR
             61 LOAD_CONST               4 (4273157)
             64 COMPARE_OP               2 (==)
             67 POP_JUMP_IF_FALSE      161

and

 23     >>  161 LOAD_FAST                4 (regs)
            164 LOAD_CONST               3 ('EIP')
            167 BINARY_SUBSCR
            168 LOAD_CONST              15 (4278021)
            171 COMPARE_OP               2 (==)
            174 POP_JUMP_IF_FALSE      276

If you look at out.txt (in attachment) you may also see what’s read from where as this python script is not complicated, and python byte code is quite easy to understand.

So just set EIP to be 413405 and run script, and you will get 1st key. Then set EIP to be 414705 and run scrip again. If you did, everything correct you should see in Log of Immunity Debugger this:

Key.png

So final key is Never_up_N3v3r_1n

Greetings

I would like to say tnx to my ARTeam mates, vnsecurity guys, and rd , and of course to superkhung for listening to my random blabing on skype during CTF :)

Author

deroko of ARTeam

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

WOWHacker CTF – Challenge 2 and Challenge 9

August 26, 2009 by thaidn · Leave a Comment 

Challenge 2

Challenge 2 is simple yet interesting. The initial target is a Python 2.2 byte-compiled file, so the first job is to decompile it to get the source code. Fortunately, decompyle just works:

$ decompyle newbie.pyc

Thu Aug 27 02:13:25 2009
# emacs-mode: -*- python-*-
import urllib
def some_cryption(arg):
    pass
a = 'http://'
dummy = 'http://korea'
b = 'uxcpb.xe'
b = b.encode('rot13')
c = 'co.kr'
cs = '.com'
d = '/vfrp/uxuxux'
dt = '/hackers'
d = d.encode('rot13')
dx = 'coolguys'
ff = urllib.urlopen(((a + b) + d))
f_data = ff.read()
file = open('hkhkhk', 'w')
file.write(f_data)
some_cryption(f_data)
file.close()

You can see that the purpose of this script is to download some data from a fixed URL, and save them to a file named hkhkhk. We ran the script, and it indeed downloaded this file. As the script suggests, the content of hkhkhk is encrypted by some cipher. 

Opening hkhkhk in a hex editor, one could see that it contains quite a lot of 0×77 characters. A friend of us, Julianor from Netifera, thought that hkhkhk is an executable file, and because excutable file contains a lot of null bytes so 0×77 may be the null byte in the original file. He suggested xoring the content of hkhkhk against 0×77. We did as he suggested, and it worked :-D. hkhkhk turns out to be an ELF executable file:

$ file hkhkhk
hkhkhk: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped

$ ./hkhkhk
./hkhkhk [server] [port]

---------------------------
server&gt; 221.143.48.88
port&gt; 1111, 2222, ..., 9999
---------------------------

Disassembling hkhkhk reveals that this binary is just a simple client that connects to a remote server to get two integers, and send the sum of them back to that server. If the result is correct (which is always), the server will return a congratulation message like below:

$ ./hkhkhk 221.143.48.88 1111
[(867925) + (9792)] = ?
answer is 877717
it's correct. great!, :-)

At first, we thought we should try to exploit the server to force it to return an error or something, but that didn’t work. Then we thought there’s something hidden inside hkhkhk, so superkhung and I spent 1 hour to inspect every single instruction of the binary, but we saw nothing weird.

At this point, a friend suggested us running the binary inside a debugger. He thought that there may be something hidden in the communication between the server and hkhkhk.

The communication? I fired up wireshark, and to my surprise, I saw the answer right away: Pandas likes hkpco XD. It turns out that the congratulation message is something like:

it's correct. great!, :-)<b>\x00</b>Password is "Pandas likes hkpco XD"

This message is passed to a printf call, and since printf expects a null-terminated string, one could never see the characters after the null byte if he doesn’t run the binary inside a debugger, or sniff the communication like us.

Challenge 9

Challenge 9 (IP: 221.143.48.88; port :4600) is a remote stack-based buffer overflow exploitation. It’s interesting because WOWHacker doesn’t release the binary as other usual exploitation challenges.

While I was banging my head against challenge 8, gamma95 told me that he could crash challenge 9 with 293 bytes. He thought that this challenge is very obvious, and wondered why none was working on it.

Actually we were very short on manpower in the first day of the premilinary round. So we chose to work only on those challenges that we were interested in or had a larger chance of solving them.

When I first saw challenge 9, I thought this challenge should be hard. Blind remote exploitation is supposed to be hard you know. This wrong assumption plus the fact that I haven’t practiced software exploitation in the last several months made me decide to leave this challenge for other teamates who might join us in the second day.

But it turns out this challenge is an easy one.

In order to exploit a stack-based buffer overflow vulnerability, one must know which address to return to. Fortunately, WOWHacker gives us a very helpful hint:

Mr.Her give you something "call me~ call me~" : bfbfeaf2

So 0xbfbfeaf2 is the return address. Normally this address should point to the beginning of our input buffer which in turn should have this structure:

&lt;SHELLCODE&gt;&lt;NOP SLED&gt;&lt;\xf2\xea\xbf\xbf&gt;

The next problem is to determine how many bytes we need to control the EIP. The trick is to use \xeb\xfe as the shellcode, and increase the message one byte a time until we see the service hang after it processes our input. If our theory of the structure of the input buffer is correct, this process will succeed eventually because \xeb\xfe means “loop forever”:

$ echo -ne '\xeb\xfe' | ndisasm -
00000000  EBFE              jmp short 0x0

Using this technique, we can see that we need totally 302 bytes to control the EIP:

$ (python -c 'print "\xeb\xfe" * 149 + "\xf2\xea\xbf\xbf"'; cat) | nc 221.143.48.88 4600

We use Metasploit to generate a BSD reverse-shell shellcode, and we got the answer: WOWHACKER without beist.

Actually this wasn’t as easy as we write here. We made two stupid mistakes: first off, we assumed that this challenge ran on a Linux box; secondly, our connect back box was behind a firewall :-(. Thanks Tora and biest for giving us a hand in resolving them.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

WOWHacker CTF – Bonus Challenges

August 26, 2009 by superkhung · Leave a Comment 

Challenge 15

2009ISEC.apm is actually an Android Package file. Rename 2009ISEC.apm to 2009ISEC.apk, install it on an Android phone, then run it, tap on the About button, and you’ll see the answer which is Wowhacker$%hinehong(ISEC)#$boann.

Challenge 16

Challenge 16 is a Windows reversing challenge. The binary fishing.exe has a hidden form named TForm2. To see this form, one can replace the parameter of the first Createform() call at 00475EDC by the parameter of TForm2.

Original asm code:

00475ED6   MOV EDX,DWORD PTR DS:[4754D8] ;  00475524 &lt;&lt; value of TForm1
00475EDC   CALL 00453694

Patched asm code:

00475ED6   MOV EDX,DWORD PTR DS:[475134] ;  00475180 &lt;&lt; value of TForm2
00475EDC   CALL 00453694

TForm2 asks for a password, then it does some calculations and compares the result with MTRJ\TWQI7dUwnijTkMnLEWf.

The password processing routine starts at the loop at 004753B2:

004753B2  MOV EAX,DWORD PTR SS:[EBP-8]
004753B5  MOV BL,BYTE PTR DS:[EAX+EDI-1]
004753B9  CMP BL,20
004753BC  JE SHORT 004753DB
004753BE  LEA EAX,DWORD PTR SS:[EBP-8]
004753C1  CALL 00404384
004753C6  MOV EDX,EDI
004753C8  DEC EDX
004753C9  SAR EDX,1
004753CB  JNS SHORT 004753D0
004753CD  ADC EDX,0
004753D0  ADD EDX,EDX
004753D2  SUB BL,DL
004753D4  ADD BL,0A
004753D7  MOV BYTE PTR DS:[EAX+EDI-1],BL
004753DB  INC EDI
004753DC  CMP EDI,1A
004753DF  JNZ SHORT 004753B2

Notice that this routine is very simple, the most important are 2 operations at

004753D2 and 004753D4:

004753D2  SUB BL,DL
004753D4  ADD BL,0A

To reverse this routine, we just change subtract to add and add to subtract,  then input the encrypted password string to find out the original password.

Patched asm code:

004753D2  ADD BL,DL
004753D4  SUB BL,0A

After patching the asm code like that, we enter the encrypted password string MTRJ\TWQI7dUwnijTkMnLEWf into TForm2, and set a break point at the first argument of LStrCmp() function at 004753E1 to sniff out the decrypted password.

004753E1  MOV EAX,DWORD PTR SS:[EBP-8] ; EBP-8 will store the decrypted password
004753E4  MOV EDX,DWORD PTR DS:[479C8C]
004753EA  CALL 00404278 ; call LStrCmp()

We will see that encrypted string MTRJ\TWQI7dUwnijTkMnLEWf will be decrypted to CJJBVNSMG5dUypmnZqUvVOcr. Use this password on the original app, and we get the final answer: HOMEWORLD2_PrideOfHiG@Ra.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

Fun code snippet

May 11, 2008 by lamer · 1 Comment 

This small snippet is copied from a much popular application.

.text:1000EBE0 push ecx ; some_string
.text:1000EBE1 push '%'
.text:1000EBE3 push '%'
.text:1000EBE5 push offset aCsystemdriveCS ; "%cSystemDrive%c%s"
.text:1000EBEA push edx ; buffer
.text:1000EBEB call ds:swprintf

Translated to C:

swprintf(buffer, "%cSystemDrive%c%s", '%', '%', some_string);

Of course you’d be scratching your head to explain why the writer wrote it this way, instead of simply swprintf(buffer, "%%SystemDrive%%%s", some_string);. To show off great C-kungfu? Or the lack thereof? Anyway, I just thought it was funny enough to post.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Add to favorites
  • Reddit
  • Technorati
  • Tumblr
  • Twitter
  • Slashdot
  • Identi.ca

Next Page »