File: DelphiChallenge.exe

SHA256: A2A27852B07B10CC02C9767A4AF2D9905C1CAB131E9411DDD9BC04FA67D4E62F

Packed: Yes

Architecture: 32Bit

Tools used: exeinfo, IDA Pro, OllyDbg

Codes & Binaries:

Description: This challenge is written in Delphi. Unpack it and reverse to get the flag.

Figure 1. Evidence of the challenge being packed

Needless to say much. The challenge is packed. Let’s Unpack it shall we =)

Looking at IDA Pro we can see the following jmp instruction at the end of the graph. Tracing the jmp instructions bring us to the figure below. @0x6F10CA the codes doesn’t look right…¬†Perhaps we could place a breakpoint @0x6F1865 and look into it.

Figure 2. IDA Pro suspicious jump

On hitting the breakpoint @0x6F1865 , we can see that 0x6F10CA had been modified.

Figure 3. In memory code modification

Now let’s take a look at the memory map (figure 4). So far there are nothing of interest here…

Figure 4. Memory Map

Interestingly after calling the function @0x006f1105, the memory maps get filled with tons of stuff. A interesting thing to note is the EAX (OEP)¬†after calling¬†0x006f1105. Seems to me that the original code has been unpack to 0x400000 memory range….

Figure 5. Code unpacked

To prove that 0x400000 contains the original code and not some random heap allocation… Let’s take a look at its content. From the figure below, we can clearly see that an executable has been copied to the memory @0x400000.

Figure 6. MZ Header spotted

In the following figure we can see a jmp to EAX; the OEP of the original challenge.

Figure 7. jmp EAX

Take the jmp and dump the process using the ollydbg plugin as shown below.

Figure 8. dumping process

However, the dumped process fails to run properly… looks like we need to fix the import table.Fire up Scylla tool and fix the dump!

Figure 9. Fixing the dump

Note that while Scylla managed to locate the VA, it fails to detect the correct size initially. We could use ollydbg to identify the size and enter it manually into Scylla as shown above.

Figure 10. End of imports

You may find the unpack challenge at the github link provided. On execution, you should see the following user interface.

Figure 11. Delphi Challenge unpacked

Back to finding flag!

Let’s do a search for the text “wrong” in IDA Pro.

Figure 12. _TFORM1_Timer1Timer?

Let’s do some x-referencing…

Figure 13. x-referencing
Figure 14. Label3Click

Tracing from click we arrive at the following function… in which we can observe something of interest. A comparison of “PAN{“. So we know that the flag is near… once we click on Enter button, this function gets triggered and there is a check on the key entered.

Figure 15. PAN{

further down we see how the 5th character of the flag is encoded. @0x00450F3D we can see that it is trying to cmp ebx with 0xCF. This value is derived¬†after xoring with 0xAB @0x00450F37. Doing the math… 0xCF ^ 0xAB == 0x64 (ASCII D) therefore the 5th character is D.

Figure 16. FLAG_5

Instead of having multiple screenshots here… i shall cut it short using¬†a table. To see how the flag is derived, trace upwards from the cmp address provided. Note that when we try to reverse a shift right operation, we would lose some data… therefore there are some cases where we need to guess what is the exact value. e.g. pos 14.

pos cmp address Math Transformation Value
 1  0x00450EAF  None  P
 2  0x00450ECD  None  A
 3  0x00450EEB  None  N
 4  0x00450F09  None  {
 5  0x00450F3D  0xCF ^ 0xAB = 0x64  d
 6  0x00450F4C  0x1E ^ 0x2D = 0x33  3
 7  0x00450FA0  0x52 ^ 0x3E = 0x6C  l
 8  0x00450FAC  0x52 ^ 0x22 = 0x70  p
 9  0x00450FBB  0x60 & 0x8 =  0x68  h
10  0x00450FC5  0x68 + 1 = 0x69  i
11  0x00450FE6  0xBA ^ 0xE5 = 0x5F  _
12  0x0045100A  0xBE ^ 0xD7 = 0x69  i
13  0x00451060  0xE6 / 2 = 0x73  s
14  0x0045106E  0x2F << 1 = 0x5E  _ or ^
15  0x0045107D  0x194 >> 2 = 0x65  e
16  0x0045108E  (0x19 << 1) + 2 = 0x34  4
17  0x004510E5  (0x1C0 ^ 0xC) >> 2 = 0x73  s
18  0x004510F6 (0x38 & 0x4) << 1 = 0x78  x or y
19  0x00451107 (0x28 + 0x7) << 1 = 0x5E   _ or ^
20  0x00451118 ((0x8C / 5) / 2) << 3 = 0x70  p Рw
21  0x00451137 0x60 / 2 = 0x30  0
22  0x00451155 0x17c >> 2 = 0x5F  _
23  0x00451178 (0x59 ^ 0x60) << 1 = 0x72  r or t
24  0x0045119B (0x42 ^ 0x88) / 2 = 0x65  e
25  0x004511BD (0x2C ^ 0xC0) / 2 = 0x76  v
26  0x004511DF (0x16 << 1) + 7 = 0x33  3
27  0x00451206 (0x36 ^ 0x29A) / 3/ 2 = 0x72  r
28  0x0045122A (0x130F0 >> 3) ^ 0x2486 >> 3 == 0x53  S
29  0x0045124E ((0x2950 ^ 0x25A0) >> 4) / 3 = 0x45  E
Figure 17. Flag secured!

FLAG: PAN{d3lphi_is_e4sy_t0_rev3rSE}



File: revloader.exe


Packed: No

Architecture: 64Bit

Tools used: exeinfo, IDA Pro, Cuckoo Sandbox, cerbero profiler

Codes & Binaries:

Description: This challenge installs a driver on the target machine. Reverse the driver to get the flag!

Figure 1. 64 bit executable

The binary is not pack… looking through the strings we can see some interesting stuff.

Figure 2. interesting strings

Firing up Cerbero Profiler, we can see 3 resources embedded in the binary. 2 executables and 1 text file.

Figure 3. resources

I shall attempt to use cuckoo sandbox to aid in my analysis (well i am lazy =D). Interestingly revloader.exe dropped 3 files in temp folder as shown below. We can also see a VBoxDrv.sys dropped by dsefix.exe. The use of this driver reminds me of a exploit few years ago that makes use of a VBox driver exploit to gain privilege escalation. Well let’s analyze this some other day. For now we shall stay focus on getting the flag.

Figure 4. cuckoo box’s written files

In cuckoo box, we can download the files that has been written on disk.

Figure 5. Download written files

Analyzing revhunt.sys via IDA Pro,w e can see some interesting strings.

Figure 6. revhunt.sys’s string

Looks like there is a high chance that the flag is hidden in this driver.

Figure 7. OMG we are getting nearer to the flag.

Now if we look at 0x001400014D9, we can see that a function is called. In which the return result determines whether the flag is shown! Lets jump right in to the function @0x000000014000181C to see if we can find anything interesting.

Figure 8. PAN flag in 0x0014000181C subroutine

From the above figure, we can see that a variable is being checked against with the string “PAN{“. Let’s analyze further down…

Looking at the figure below, @0x0140001946 we can see a cmp operations. Seems like the value is obtained after xoring with 0x1A1B1C1D (@0x014000193E). Doing a reverse xor…. eax should contain 0x2C776F57 in order to pass the cmp test. 0x2C886F57 === ,woW (to be exact Wow, -> little endian).

Figure 9. We got more characters!

so far the flag is PAN{Wow, ????

Cool looks like we are on the right track! For simplicity i have tabulated a table for decoding the flag.

pos cmp address math transformation value
1 0x0000000140001913 None P
2 0x000000014000191D None A
3 0x0000000140001927 None N
4 0x0000000140001931 None {
5-8 0x0000000140001946 0x366C734A ^ 0x1A1B1C1D = 0x2C776F57 Wow,
9 0x000000014000196C (0xF0 ^ 0xB0) >> 1 = 0x20 [space]
10 0x000000014000198 (0x56 ^ 0x20) – 4 = 0x72 r
11-18 0x0000000140001990 0x8888999900001110 ^ 0x0A9FAFCEA72656770 = 0x2172657372657660 [` – o]verser!
19 0x0000000140001B30 None [space]
20 0x0000000140001B3C 0x67 ^ 0x20 = 0x47 G
21 0x0000000140001B71 None r
22 0x0000000140001B58 0xFC ^ 0x99 = 0x65 e
23 0x0000000140001B4B 0xC3/3 + 0x20 = 0x61 a
24 0x0000000140001B7D 0x3B ^ 0x4F = 0x74 t
25 0x0000000140001B66 None [space]
26 0x0000000140001B89 (0x71 – 0xf) ^ 0xf = 0x6D m
27 0x0000000140001BA4 (0x81 ^ 0x21) – 0x31 = 0x6F o
28 0x0000000140001B95 0x46 ^ 0x30 = 0x76 v
29 0x0000000140001BB9 0x58 + 0xC + 1= 0x65 e
30 0x0000000140001BC2 none s
31 0x0000000140001BFC none ,
32 0x?? none  [space]
33 0x0000000140001C08 0x1AC0 >> 6 = 0x6B k
34 0x0000000140001C1A X*8 +0xFFFFFFE0 == 0x308 e
35 0x0000000140001C31 ((0xE002 ^ 0xF2F2) >> 4) / 3 = 0x65 e
36 0x0000000140001C45 (0x9542 ^ 8942) >> 6 p
37 0x?? none [space]
38 0x0000000140001C6D ((0x834 << 2) >> 4) /5 = 0x69 i
39 0x0000000140001C81 (0x94DD ^ 0x83c1) / 0x33 = 0x74 t
40 0x0000000140001C56 0x1F + 1 = 0x20 [space]
41 0x0000000140001CC5 (0x1DD36C ^ 0x46) / 0x4142 = 0x75 u
42 0x0000000140001CAC 0x328250 / 0x7373 = 0x70 p
43 0x0000000140001C98 0x2D – 1 = 0x2C ,
44 0x0000000140001D09 0xB6 ^ 0x32 = 0x2C ,
45 0x0000000140001D29 0x40 – 0x20 = 0x20 [space]
46 0x0000000140001D1B (0xD7 ^ 0x44) – 0x23 = 0x70 p
47 0x0000000140001D3B (0xB2 ^ 0x21) – 0x21 = 0x72 r
48 0x0000000140001D4D ((X*4)+7C) & 0xFF == 0x38 o
49 0x0000000140001D5D (0x8F25 ^ 0x8875) >> 4 = 0x75 u
50 0x0000000140001D72 (0xd6 ^ 0xE4)/2 >> 2 = 0x64 d
51 0x0000000140001D84 (0x62^0x42) = 0x20 [space]
52 0x0000000140001E05 (0x70D49 ^ 0x48354) / 0x833 = 0x6F o
53 0x0000000140001E1D (0x14C3A1 ^ 0x232221) / 0x8C40 = 0x66 f
54 0x0000000140001DE3 && 0x0000000140001DEE must be same as 50 && btc 0xA0, 7 == 0x20 [space]
55 0x0000000140001E5F 0x5C ^ 0x25 = 0x79 y
56 0x0000000140001E71 (0x20F63 ^ 0x23) / 0x4C0 = 0x6F o
57 0x0000000140001E89 (0x242067 ^ 0x12567)/0x5100 = 0x75 u
58 0x0000000140001E9E ((0x61 ^ 0x21) >> 6) + 0x20 = 0x21 !
59 0x0000000140001EB3 ((0x13F ^ 0x903) / 0x44) << 2 = 0x7C (0x7C – 0x7F) }

I guessed some of the values as I did not manage to spot the cmp instructions (character 32 and 37). For character 11, the value is also guessed due to loss of data during transformation.

FLAG: PAN{Wow, reverser! Great moves, keep it up, proud of you!}



File: PuppetPals.exe

SHA256: 337D094ED647EAE05F871A0295A6DB55E1FA07BE7EB4D9DD2D0B2E45FC44C1C1

Packed: No

Architecture: 32Bit

Tools used: exeinfo, IDA Pro, OllyDbg

Codes & Binaries:

Description: This challenge is written in C++. A PCAP file given. Decrypt the message that is hidden in the traffic to get the flag.

Figure 1. First look

The above figure tells us a lot of stuff.

  1. It is likely that it is not packed
  2. It is probably attempting to connect to an IP (
  3. There are some sort of debug messages
  4. uses socket to send data out

Let’s try to get the flag!

Figure 2. Socket

x-referencing from the import list we will see the above figure. Looks like the challenge is attempting to connect to It seems to only send 1 character at a time… Now, I want to¬†know what is being send over the network.¬†Tracing who calls this function bring¬†us to the figure below.

Figure 3. Steal, encrypt, encode, Send


The figure above shows that the challenge reads content from file.txt, encrypt the content, encode the encrypted content and send it out.

Let’s take a look at 0x00412359. How did I derive that it is a base64 encoding function? Take a look at 0x00411840 and you will see some¬†tell tale signs as shown in the figure below. Most importantly I see “=” sign being appended near the end of the function.

Figure 4. 0x00411840
Figrue 5. 64 character long string

Here is a piece of code i grabbed from online of a base64 implementation.

Figure 6. Base64 implementation

Notice there are some similarities between the code and the assembly codes. However the basis_64 variable seems to be different. Custom base64 encoding??? That is my guess. Now is there anyway to prove it? Let’s get our hands dirty with ollydbg! First create a file “file.txt” and placed it together with the challenge executable’s location. Put some contents in it… for my case I entered “AAAABBBBCCCCDDDDEEEEFFFF” into file.txt

We shall set breakpoint at

  1. 0x0412345 – call to suspected encryption routine
  2. 0x041234A – after encryption routine (or use F4 to break @ here)
  3. 0x0412359 Рcall to suspected base64 routine
  4. 0x041235E Рafter encoding routine (or use F4 to break @ here)
Figure 7. Visualizing encrypting and encoding in action via ollydbg

In the above figure, we can see that the string¬†“AAAABBBBCCCCDDDDEEEEFFFF” and its length 0x18 (decimal 24) is passed into the subroutine @ 0x00411127.

Figure 8. encrypted

After the routine, we can see that the value in the memory has changed. It seems like the encrypted data has the same length as the plain text.

Figure 9. encoding

@0x0412359 we can see that the encrypted data is passed into the routine @004111B3 (our suspected base64)… Let’s do a quick check here. We shall change the encrypted contents to “PIKACHU THUNDERBOLT NOW!

Figure 10. edit binary: PIKACHU

Run to the next breakpoint @0x041235E (after the encoding routine).

Figure 11. encoded

We can see from the memory address pointed by eax that there are some garblish data in it… “GYc4QGlypBtGBKpz/YpBQ9UfpgtzsPVC

Now we shall use an online tool for a quick check… ( using “qtgJYKa8y5L4flzMQ/BsGpSkHIjhVrm3NCAi9cbeXvuwDx+R6dO7ZPEno21T0UFW” as the custom¬†key.

Figure 12. custom base64 online tool

As shown from the above figure, we indeed decoded the encoded data back to our pikachu text! Now we need to figure out how the encryption is done and we are almost there. Sadly i don’t have a lazy/simple solution here. I reversed the encryption algo into php code and did a algo reversal to get the plain text from the encrypted data. You may find the encryption code and decryption code in the github link provided.

Back in figure 2, we mentioned that only 1 byte is sent at a time to Using scapy we can extract the data out from the pcap (as shown below).

Figure 13. extract data from pcap

Analyzing the encryption routine, you will see that “AWildKeyAppears!” is being used as a key to encrypt the data.

Figure 14. Reversing the encryption routine (part 1)

The following is a php code of the encryption routine found in the challenge.

Figure 15. Reversed Encryption routine

The following is the codes to reverse the encryption process. Basically it undo what an encryption routine does.

Figure 16. Reversing the encryption algo


Running the extracted data with the codes I had reversed earlier…

Figure 17. Flag secured

FLAG: PAN{did_1_mention_th0se_pupp3ts_fr34ked_m3_out_recent1y?}



File: Ambrosius.exe

SHA256: 54CB91340DBC073FB303A7D920E26AA1D64F9EE883D6AAE55961A76D5AFF91F4

Packed: No

Architecture: 32Bit

Tools used: exeinfo, IDA Pro

Codes & Binaries:

Description:¬†This challenge is written in C. The goal is to find the correct password such that the decrypted¬†string will begins with “PAN{?????

Figure 1. Unknown EXE?

IDA Pro’s strings list and Import list did not surface any findings….

Scrolling down the codes, the first thing that caught my eyes is a check on PAN{. Perhaps we could work our way up from here.

Figure 2. PAN{

Tracing upwards we can assume that a password of length 11 is passed into a decrypt function (0x401425). Analyzing further upwards, we start to see how the password is formed.

Figure 3. b00?????

The following are the instructions that built the password string. Note: The challenge uses a shellcode approach to get values/call functions from the system.

Address Instructions Possible Values
0x00401158 MOV BYTE PTR DS:[EAX],62 b
0x0040116A MOV BYTE PTR DS:[EAX+1],30 0
0x00401166 MOV BYTE PTR DS:[EAX+2],30 0
0x0040114B MOV BYTE PTR DS:[EAX+3],21 !
0x00401383 MOV BYTE PTR DS:[ECX+4],DL 0x2d + month
0x0040138F MOV BYTE PTR DS:[ECX+5],DL 0x5e + day
0x004013AB MOV BYTE PTR DS:[ECX+6],DL 0x42 + hour
0x0040132C MOV BYTE PTR DS:[ECX+7],DL A,B,F (Minor Version)
0x00401336 MOV BYTE PTR DS:[ECX+8],DL ?,@,A,B (Major Version)
0x0040139F MOV BYTE PTR DS:[ECX+9],DL i,j (isDebugger)
0x00401152 MOV BYTE PTR DS:[EAX+0A],BL 0x5e + 0xc,0x14,0x00,0x08,0x10,0x04(language)

from the above figure, we know that the password have 4 fixed values out of 11 characters. The remaining 7 characters can be bruteforced.

The lazy way that I used for this challenge is to use a python debugging script and break @ 0x00401425. Once broken into the program, the python script shall overwrite the password with our generated password.

To check if we got the correct password, I placed another breakpoint @0x0040143B (refer to figure 2). If we were to hit this breakpoint, it simply means that we have found the correct password.

I used¬†php to generate the possible password lists and feed it into the python script (refer to GrayHat Python) to test the password on the executable. This approach is definitely not the fastest way to solve the¬†challenge but I think it is the laziest way to do it… =D

Figure 4. Generate passwords

For the python debugging script, I used the sample given by “Grayhat Python”. I simply mod the script to inject generated password and detect if it has found the correct password. =)

Figure 5. modded codes
Figure 5. Yeah flag secured

Probably not the neatness way to solve the challenge… but it works!

FLAG: PAN{th0se_puPP3ts_creeped_m3_out_and_I_h4d_NIGHTMARES}



File: RGB.exe


Packed: No

Architecture: 32Bit

Tools used: exeinfo,Reflector

Codes & Binaries:

Description: This challenge is written in C#. One would need to figure the correct RGB value to get the flag. Just decompile and analyze the code to get the RGB value.

Figure 1. The challenge

Based on the figure below, we know that this is a C# program.

Figure 2. C# program

Using decompiler like reflector, we can easily get the decompiled source code. I have placed the source code in github for you to play with.

Figure 3. Main algo to derive the key

Analyzing the source codes, we will come across the above function in frmMain.cs. Looks like we need some bruteforcing to get the correct RGB key.

Figure 4. My simple bruteforcing script

Running the above script, we would be able to get the correct RGB to solve the challenge.

Figure 5. Flag secured

FLAG: PAN{l4byr1n7h_s4yz_x0r1s_4m4z1ng}



File: JugsOfBeer.exe

SHA256: 59E71EE7A6C110D77CB19337EF2E7DA26C9E367D44588C09C6A4635D91318D0A

Packed: No

Architecture: 64Bit

Tools used: exeinfo, IDA Pro

Codes & Binaries:

Description: This challenge is written in C and compiled as a 64 bit binary. It is a modified version of the Water pouring puzzle. To solve this challenge, you would need to find the shortest number of steps required to get to the specified end state.

Figure 1. The challenge

The challenge is expecting an input from the user. Ahhh typical serial cracker challenge? Let’s check if it is packed via exeinfo and IDA Pro.From the figures below, we can conclude that the binary isn’t packed. =D

Figure 2. Not packed =)
Figure 3. IDA Pro’s string list

Let’s start analzying… Back Tracing from the string as highlighted in the above figure, we will come across the following function @¬†0x0140001280.

If you were to analyze the function, you will come across a strlen check.

Figure 4. length check

From the above figure, we know that the input string must be 32 character long. Further down, we will come across a check to ensure that the input characters must be >= 0x31 && it must also be <= 33.

To check it manually, suppose we enter 0, which is equivalent to 0x30. Adding 0x30 to 0xFFFFFFCF will give us 0xFFFFFFFF which is above 2 therefore failing the check test.

If we were to enter the value 4, the summation will give us 0x100000003. Now eax takes only the last 4 bytes and therefore we are comparing 3 to 2. As 3 is larger than 2, we fail the test again.

The only values that will pass this test is between 1 and 3.

Figure 5. Validate inputs

If we manage to clear all the validation test, we would then reach the address 0x14000151C in which a function(0x140001750) is called. If this function returns 0, we would get a “try again” message. So it seems like we would need to ensure that this function returns a 1.

Figure 6. Initial State

Zooming into the function @ 0x140001750, we can see that it set a variable initial state into 0x0, 0x0, 0xD, 0x7.

Figure 7. End state

Further down the function, we will come across the end state that we wanted 0x??, 0xA, 0xA, 0x??. With that the code will set eax to 1!

What can be observed is that with the given inputs, the state of the variable changes accordingly. In other words we must give the correct input such that the end state of the variable become 0x??, 0xA, 0xA, 0x?? from 0x0, 0x0, 0xD, 0x7.

We know that the input is expecting 32 characters which equates to 16 combinations based on the puzzle. Each combination can be in the form of 0x11, 0x12, 0x13, 0x21, 0x22, 0x23, 0x31, 0x32, 0x33. However the state wont change if the input values are 0x11,0x22,0x33. This reduces out possible inputs to only  0x12, 0x13, 0x21, 0x23, 0x31, 0x32.

6^16 == forever…. thus bruteforcing might not be a wise choice.

SMT Solver would do the job…. but let’s try the easier approach of manual processing first =D. I reversed the code in 0x140001750 into a php script. You may find the script in the github link provided. Now let’s do some observation.

The above figure shows something interesting. We tested 6 different possible combination for the first input and we end up with only 3 distinct outcome. The first outcome is being back to the initial state. Which leaves us with only 2 distinct outcome. From the figure below, we would just need to either go down the path from 21????? or 31?????.

Figure 8. Bruteforcing first input

Hypothesis ==> if we only go down unique paths, we could potentially reach the end state without taking forever!

Figure 9. Solved in under 1 second
Figure 10. Yeah we got the flag

FLAG: PAN{C0ngr47ulaT1ons_buddy_y0Uv3_solved_the_re4l__prObL3M}