Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 84161ec
Showing
40 changed files
with
7,855 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
|
||
This is my write-up repository for single person CTF. | ||
|
||
See [Play4Fun](http://p4f.github.io) for write-ups from my current team and [Rentjong](https://github.com/rentjongteam/) for my Indonesian team. | ||
|
||
Current write-up: | ||
|
||
* [Flare On 2015](flare-2015) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Flare-On 2015 | ||
|
||
|
||
Content | ||
|
||
* [Challenge 1](flare1) | ||
* [Challenge 2](flare2) | ||
* [Challenge 3](flare3) | ||
* [Challenge 4](flare4) | ||
* [Challenge 5](flare5) | ||
* [Challenge 6](flare6) | ||
* [Challenge 7](flare7) | ||
* [Challenge 8](flare8) | ||
* [Challenge 9](flare9) | ||
* [Challenge 10](flare10) | ||
* [Challenge 11](flare11) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Challenge 1 | ||
|
||
This is so trivial. You can see the complete tutorial to solve it in the webinar (which I didn't see until I finished all the challenges). The only thing I want to show here is that I solved this using objdump, I didn't have access to Windows when I downloaded the first challenge: | ||
|
||
objdump -p -s -d i_am_happy_you_are_to_playing_the_flareon_challenge.exe | ||
|
||
I know its not easy to read it, and it didn't occur to me to use online disassembler, but with a bit of concentration we can immediatelly see that `push $0x4020f2` refers to the string `"Let's start out easy\r\nEnter the password>"`. Address `$0x402158` will contain the result of `ReadFile`, and it will be compared with block at `0x402140` after xoring it with fixed key `0x7d`. So basically this is just XOR encryption, 24 characters (`"cmp $0x18,%ecx"`). | ||
|
||
objdump -s --start-address=0x402140 --stop=0x402158 i_am_happy_you_are_to_playing_the_flareon_challenge.exe | ||
|
||
And this one line of python is enough to solve it: | ||
|
||
print "".join([chr(ord(x) ^ 0x7d) for x in "1f08131304220e114d0d183d1b111c0f18501213531e1210".decode("hex")]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Challenge 10 | ||
|
||
This file is an `AutoIt.exe`. It can be extracted using: Exe2Aut.exe. The autoit script doesn't do anything meaningful except for installing the driver and calling IOCTL, so I went to look at the driver. The driver contains many functions, mostly junk, except for parts where it writes a byte to certain memory location. | ||
|
||
I am still not sure how to separate the junk instructions, so I just wander around the code to see if there are something that is clear and doesn't contain junk. One thing pops up: a number that is used as constant to TEA encryption algorithm. The input for the algorithm is a memory location, and a fixed key. | ||
|
||
I am too lazy to setup an environment to debug the code, so I just used Ida's xref function to trace one by one the bytes written to the memory location that is decrypted. I traced the first 8 bytes, tried to decrypt it, and got a plaintext `uncondit`, it looks right, so I just continued to the next bytes, until I got the string: `unconditional_conditions@flare-o`, and just stops there. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#include <stdio.h> | ||
|
||
unsigned int TEA(int *a1, int *a2) // | ||
{ | ||
unsigned int result; // eax@4 | ||
unsigned int v3; // [sp+0h] [bp-24h]@1 | ||
signed int v4; // [sp+14h] [bp-10h]@1 | ||
unsigned int v5; // [sp+18h] [bp-Ch]@1 | ||
unsigned int i; // [sp+20h] [bp-4h]@1 | ||
|
||
v3 = *a1; | ||
v5 = a1[1]; | ||
v4 = 0xC6EF3720; | ||
for ( i = 0; i < 32; ++i ) | ||
{ | ||
v5 -= (a2[3] + (v3 >> 5)) ^ (v4 + v3) ^ (a2[2] + 16 * v3); | ||
v3 -= (a2[1] + (v5 >> 5)) ^ (v4 + v5) ^ (*a2 + 16 * v5); | ||
v4 += 0x61C88647; | ||
} | ||
*a1 = v3; | ||
result = v5; | ||
a1[1] = v5; | ||
return result; | ||
} | ||
|
||
void decrypt(char *ax) | ||
{ | ||
int key[] = {0x33323130,0x37363534,0x42413938,0x46454443, 0}; | ||
TEA((int *)ax, key); | ||
printf("%s", ax); | ||
} | ||
|
||
int main() | ||
{ | ||
|
||
char ax1[] = "V\x7F\xDC\xFA\xAA\x27\x99\xC4\x00"; | ||
decrypt(ax1); | ||
char ax2[] ="\x6c\x7c\xfc\x92\x61\x61\x47\x1a\x00"; | ||
decrypt(ax2); | ||
char ax3[] ="\x19\xb9\x63\xfd\x0c\xf2\xb6\x20\x00"; | ||
decrypt(ax3); | ||
char ax4[] = "\xC0\x2D\x5C\xFD\xD9\x71\x54\x96\x00"; | ||
decrypt(ax4); | ||
printf("\n"); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Challenge 11 | ||
|
||
Note: This write up is not as complete as I want it to be. May be I will update it someday. | ||
|
||
Reading the easy part of the code: this app tries to decrypt a resource file to "secret.jpg". Like the challenge #4, it reads a single argument from command line, but this time brute force doesn't work. Even given the correct parameter, the program just hangs. | ||
|
||
I tried to extract the encryption code so I can just call it, but there are too many functions being called. I tried reimplementing it, but its too complicated. | ||
|
||
For the first part: finding the correct parameter, I just patched the binary, so it will exit with esi as the return value (`call exit(esi)`) after the first MD5 comparation. When `esi` is less than 0, it means I got the correct parameter. | ||
|
||
Here is the patch: | ||
|
||
fc CryptoGraph.exe CryptoGraph-patched.exe | ||
Comparing files CryptoGraph.exe and CRYPTOGRAPH-PATCHED.EXE | ||
00000B29: 85 56 | ||
00000B2A: FF E8 | ||
00000B2B: 74 2E | ||
00000B2C: 09 4F | ||
00000B2D: 57 00 | ||
00000B2E: E8 00 | ||
|
||
For the second part, I finally understood that the loop is mean to create decryption key for the decryption. I also saw a bit counting algorithm being used. I have a theory that you don't need the full 32 iteration to generate the bytes necessary to decrypt the resource inside the file. | ||
|
||
First I need to be able to control the loop count, and also the return value of the bit counting mechanism. Then I wrote a python brute forcer. In another window I executed: "file *jpg", until I got: | ||
|
||
c-9.exe.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 72x72, segment length 16, baseline, precision 8, 416x416, frames 3 | ||
|
||
The patch for the second part: | ||
|
||
fc CryptoGraph.exe CryptoGraph2.exe | ||
Comparing files CryptoGraph.exe and CRYPTOGRAPH2.EXE | ||
00000CC2: 20 02 | ||
000011A6: FF 90 | ||
000011A7: 75 90 | ||
000011A8: 10 90 | ||
000011AC: FF 90 | ||
000011AD: 75 90 | ||
000011AE: C0 90 | ||
000011AF: E8 B8 | ||
000011B0: AC 02 | ||
000011B1: FD 00 | ||
000011B2: FF 00 | ||
000011B3: FF 00 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import os | ||
|
||
with open("CryptoGraph2.exe", "rb") as f: | ||
r = f.read() | ||
|
||
n = 0xcc2 #patch loop count | ||
r = r[:n] + chr(0xA) + r[n+1:] | ||
|
||
n = 0x11B0 | ||
for i in range(0, 64): | ||
c = chr(i) | ||
#patch bit count | ||
new = r[:n] + c + r[n+1:] | ||
name = "c-%d.exe" % i | ||
with open(name, "wb") as f: | ||
f.write(new) | ||
os.system(name + " 205") | ||
os.rename("secret.jpg", name + ".jpg"); | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import os | ||
for i in range(0, 1000): | ||
print "i = ", i | ||
n = os.system("CryptoGraph-patched.exe %d" % i) | ||
if (n<=100): | ||
print "-------", n | ||
with open("result.xt", "a+") as f: | ||
f.write(str(i)+"\n"); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
flare2: flare2.c func.o | ||
gcc -m32 flare2.c func.o -o flare2 | ||
|
||
func.o: func.asm | ||
nasm -f elf func.asm | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Challenge 2 | ||
|
||
This is also a small and easy challenge, and I just want to show how I used `objdump` + `nasm` to solve the problem without knowing the exact algorithm. I looked at the encryption part a little bit and I don't remember exactly the bits on the x86 flags i.e: I don't know which flags are set by `sahf` instruction, and I don't want to spend time to check and implement it. Still on Linux, I used objdump to cut the encryption part. Added this header: | ||
|
||
--- | ||
BITS 32 | ||
global func | ||
|
||
|
||
section .text | ||
func: | ||
----- | ||
|
||
And changed the addresses to labels. | ||
|
||
nasm -f elf func.asm | ||
gcc -m32 flare.c func.o | ||
|
||
And wrote this short code: | ||
|
||
```C | ||
#include <stdio.h> | ||
|
||
extern int func(char *s1, char *s2, int len); | ||
|
||
int main() | ||
{ | ||
char *a1 = "\xaf\xaa\xad\xeb\xae\xaa\xec\xa4\xba\xaf\xae" | ||
"\xaa\x8a\xc0\xa7\xb0\xbc\x9a\xba\xa5\xa5\xba" | ||
"\xaf\xb8\x9d\xb8\xf9\xae\x9d\xab\xb4\xbc\xb6" | ||
"\xb3\x90\x9a\xa8"; //edi (compare) | ||
char inp[] = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | ||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | ||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | ||
"\x00\x00\x00\x00\x00\x00\x00"; //esi (input) | ||
int i = 0; | ||
int ch = 0; | ||
int count = 0x25; | ||
|
||
for (i=0; i < 37; i++) { | ||
for (ch=0; ch < 255; ch++) { | ||
inp[i] = ch; | ||
int n = func(a1, inp, 0x25); | ||
int idx = (n & 0xff00)>>8; | ||
if (idx!=count) { | ||
printf("%c", ch); | ||
count = idx; | ||
break; | ||
} | ||
} | ||
} | ||
printf("\n"); | ||
|
||
} | ||
``` | ||
So in this case: I don't need to know how the algorithm works, just by understanding a little bit of the main loop, I can just brute force it. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#include <stdio.h> | ||
|
||
extern int func(char *s1, char *s2, int len); | ||
|
||
int main() | ||
{ | ||
char *a1 = "\xaf\xaa\xad\xeb\xae\xaa\xec\xa4\xba\xaf\xae\xaa\x8a\xc0\xa7\xb0\xbc\x9a\xba\xa5\xa5\xba\xaf\xb8\x9d\xb8\xf9\xae\x9d\xab\xb4\xbc\xb6\xb3\x90\x9a\xa8"; //edi (compare) | ||
char inp[] = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; //esi (input) | ||
int i = 0; | ||
int ch = 0; | ||
int count = 0x25; | ||
|
||
for (i=0; i < 37; i++) { | ||
for (ch=0; ch < 255; ch++) { | ||
inp[i] = ch; | ||
int n = func(a1, inp, 0x25); | ||
int idx = (n & 0xff00)>>8; | ||
if (idx!=count) { | ||
printf("%c", ch); | ||
count = idx; | ||
break; | ||
} | ||
} | ||
} | ||
printf("\n"); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
BITS 32 | ||
global func | ||
|
||
|
||
section .text | ||
func: | ||
push ebp | ||
mov ebp,esp | ||
sub esp,0x0 | ||
push edi | ||
push esi | ||
;; make it 0 | ||
xor eax, eax | ||
xor ebx,ebx | ||
mov ecx,0x25 | ||
cmp DWORD [ebp+0x10],ecx | ||
jl .done | ||
mov esi,DWORD [ebp+0xc] | ||
mov edi,DWORD [ebp+0x8] | ||
lea edi,[edi+ecx*1-0x1] | ||
.loop1: | ||
mov dx,bx | ||
and dx,0x3 | ||
mov ax,0x1c7 | ||
push eax | ||
sahf | ||
lodsb | ||
pushf | ||
xor al,BYTE [esp+0x4] | ||
xchg dl,cl | ||
rol ah,cl | ||
popf | ||
adc al,ah | ||
xchg dl,cl ; dl contains loop counter | ||
xor edx,edx | ||
and eax,0xff | ||
add bx,ax | ||
scasb | ||
jne .wrong | ||
cmovne cx,dx | ||
pop eax | ||
jecxz .done | ||
sub edi,0x2 | ||
loop .loop1 | ||
jmp .done | ||
xor eax,eax | ||
jmp .done | ||
.wrong: | ||
shl ecx, 8 | ||
or eax, ecx | ||
.done: | ||
pop esi | ||
pop edi | ||
mov esp,ebp | ||
pop ebp | ||
ret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Challenge 3 | ||
|
||
This is a huge (12 Mb) binary. I made a guess that this file must be a special binary. I looked at some clues on using strings, and it shows: | ||
|
||
mstruct | ||
mpyi_os_path | ||
mpyi_archive | ||
mpyi_importers | ||
s_pyi_bootstrap | ||
spyi_carchive | ||
selfie | ||
bMicrosoft.VC90.CRT.manifest | ||
bmsvcr90.dll | ||
bmsvcp90.dll | ||
bmsvcm90.dll | ||
bpython27.dll | ||
bselect.pyd | ||
bunicodedata.pyd | ||
bPySide.QtCore.pyd | ||
b_hashlib.pyd | ||
bbz2.pyd | ||
b_ssl.pyd | ||
bPySide.QtGui.pyd | ||
b_socket.pyd | ||
bpyside-python2.7.dll | ||
bshiboken-python2.7.dll | ||
bQtCore4.dll | ||
bQtGui4.dll | ||
belfie.exe.manifest | ||
python27.dll | ||
|
||
Ok so this was built using Python. The is a hint from the string about pyi_archive, so i tried extracting it using `pyi-archive_viewer`, and it works. There is file inside it named `"elfie"`, it reminded me of [a CTF problem where they embed an ELF file inside an ELF and called it selfie](https://github.com/smokeleeteveryday/CTF_WRITEUPS/tree/master/2015/ASISCTF/reversing/selfie). So I immediatelly looked at the file named `elfie`. Its an obfuscated python file, but can be easily decoded using `print`. | ||
|
||
In the result file, I saw the string `reversed ("moc.no-eralf@...")`, and knew immediatelly that this is the string that I am looking for. We just need to reverse it: `"".join(list(reversed("moc.no-eralf@...")))` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Challenge 4 | ||
|
||
Using `strings`, I can see that this file is packed using UPX (you can see the string `UPX0`, `UPX1`), so I decided to postpone this problem until I got an access to a Windows machine. I tried to decompress it using `upx` command line, but it doesn't run in Windows 10. I thought that this must have used a modified compressor. | ||
|
||
Anyway, I just run this inside OllyDbg. The interesting thing is: it reads from a command line, and converts the string from command line it to single byte int. 256 is very small key space, so I just brute force this without knowing what exactly this file does. | ||
|
||
for /l %x in (0, 1, 255) do youPecks.exe %x >> result.txt | ||
|
||
And you can see the answer in one of the lines. Reading others writeup, it seems that this is time dependant. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
flare5 : flare5.c enc.o | ||
gcc -m32 flare5.c enc.o -o flare5 | ||
|
||
flare5test : flare5test.c enc.o | ||
gcc -m32 flare5test.c enc.o -o flare5test | ||
|
||
enc.o: enc.asm | ||
nasm -f elf enc.asm |
Oops, something went wrong.