adding challenge 5
@@ -6,4 +6,315 @@ title: Challenge 5 pewpewboat.exe
|
|||||||
|
|
||||||
[Go Back to All Challenges](https://securedorg.github.io/flareon4)
|
[Go Back to All Challenges](https://securedorg.github.io/flareon4)
|
||||||
|
|
||||||
# Challenge 5: pewpewboat.exe #
|
# Challenge 5: pewpewboat.exe #
|
||||||
|
|
||||||
|
This was a fun challenge that required you to play mutiple rounds of a battleship game in order to reveal the answer. Remember to always check the file header before starting.
|
||||||
|
|
||||||
|
## Triage ##
|
||||||
|
|
||||||
|
As you can see this is not a windows PE binary, but instead an ELF binary:
|
||||||
|
|
||||||
|
```
|
||||||
|
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
|
||||||
|
00000010: 0200 3e00 0100 0000 e00a 4000 0000 0000 ..>.......@.....
|
||||||
|
00000020: 4000 0000 0000 0000 7033 0100 0000 0000 @.......p3......
|
||||||
|
00000030: 0000 0000 4000 3800 0900 4000 1d00 1c00 ....@.8...@.....
|
||||||
|
00000040: 0600 0000 0500 0000 4000 0000 0000 0000 ........@.......
|
||||||
|
00000050: 4000 4000 0000 0000 4000 4000 0000 0000 @.@.....@.@.....
|
||||||
|
00000060: f801 0000 0000 0000 f801 0000 0000 0000 ................
|
||||||
|
00000070: 0800 0000 0000 0000 0300 0000 0400 0000 ................
|
||||||
|
00000080: 3802 0000 0000 0000 3802 4000 0000 0000 8.......8.@.....
|
||||||
|
00000090: 3802 4000 0000 0000 1c00 0000 0000 0000 8.@.............
|
||||||
|
000000a0: 1c00 0000 0000 0000 0100 0000 0000 0000 ................
|
||||||
|
```
|
||||||
|
|
||||||
|
I typically use my ubtunu VM for ELF binary analysis. Here is the **file** command output:
|
||||||
|
|
||||||
|
```
|
||||||
|
ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=580d3cee15362410c9e7b0ae44d65d57deb52912, stripped
|
||||||
|
```
|
||||||
|
|
||||||
|
Here is some console output:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Getting Started ##
|
||||||
|
|
||||||
|
Since I am more of a windows RE person, I had to relearn using GDB. I recommend using GDB for the debugging portion. Here is a simple [GDB Cheatsheet](http://darkdust.net/files/GDB%20Cheat%20Sheet.pdf)
|
||||||
|
```
|
||||||
|
sudo apt-get install gdb
|
||||||
|
```
|
||||||
|
|
||||||
|
In the disassembly, be sure to look for:
|
||||||
|
|
||||||
|
* large chunks of referenced junk data
|
||||||
|
* input validation functions
|
||||||
|
|
||||||
|
You want to map out the execution flow as much as possible, because you will need to know the exact offsets to set your break points if you use GDB.
|
||||||
|
|
||||||
|
You should have mapped out something like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Getting started with GDB ##
|
||||||
|
|
||||||
|
1. Run GDB
|
||||||
|
```
|
||||||
|
gdb pewpewboat.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Set a breakpoint at the main function. Break at pointer 0x403D86 (main)
|
||||||
|
```
|
||||||
|
break *0x403D86
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Run and it will stop at the next break point
|
||||||
|
```
|
||||||
|
run
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Continue to running to the next break point
|
||||||
|
```
|
||||||
|
continue
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Step into to the next instruction
|
||||||
|
```
|
||||||
|
si
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Display disassembly for 20 instructions for the $pc regsiter
|
||||||
|
```
|
||||||
|
x/20i $pc
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
|
**Display Registers**
|
||||||
|
```
|
||||||
|
info registers
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
|
**Display 20 Hex Values**
|
||||||
|
```
|
||||||
|
x/20x $rbp-0x30
|
||||||
|
```
|
||||||
|
|
||||||
|
## Export Referenced data ##
|
||||||
|
|
||||||
|
Be sure to extract the referenced data at offset **6050E0**
|
||||||
|
|
||||||
|
## Seeds and Xoring ##
|
||||||
|
|
||||||
|
Each pewpew map is decoded with a seed value in function 40304F. The initial seed value is in generated in function offset `403034`. If you look up values **41C64E6D** and **3039** you will find various other code that uses this seed generator values like John's code [here](https://github.com/fideliscyber/indicators/blob/master/dga-scripts/vawtrak-dga.py). After every map is decoded it generates a new seed value which it will use to decode the next map.
|
||||||
|
|
||||||
|
From the start function:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Inside the decode function 40304F:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Useless Function ##
|
||||||
|
|
||||||
|
If you saw this ouput call for **NotMD5Hash** you really don't need it. You can just simply patch the usage of it.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Patch the binary by changing 0x74 to 0x75 which will change JZ to JNZ:
|
||||||
|
```
|
||||||
|
< 00003750: 0048 89ce 4889 c7e8 c4d2 ffff 85c0 7405 .H..H.........t.
|
||||||
|
---
|
||||||
|
> 00003750: 0048 89ce 4889 c7e8 c4d2 ffff 85c0 7505 .H..H.........u.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Breaking Down the Pewpew Map Data ##
|
||||||
|
|
||||||
|
The first 16 bytes are the coordinates for the battelships while the next 8 bytes is the initial seed.
|
||||||
|

|
||||||
|
|
||||||
|
### Coordinates ###
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
You can see where the coordinates are referenced yourself by setting a beak point at `4039E9`
|
||||||
|
```
|
||||||
|
break *0x4039E9
|
||||||
|
```
|
||||||
|
Hit continue once and it will ask you to enter a coordinate on the pewpew map and will break back at 4039E9. This is where you will want to look at the contents of [rbp+var_58]. Use these commands to view to contents.
|
||||||
|
```
|
||||||
|
>>> x/x $rbp-0x58
|
||||||
|
0x7fffffffdd58: 0x00614010
|
||||||
|
>>> x/16x 0x00614010
|
||||||
|
0x614010: 0x08087800 0x00080878 0x00000200 0x00000000
|
||||||
|
0x614020: 0x59cfcf4f 0xef6e3dba 0x00000020 0x65533242
|
||||||
|
0x614030: 0x6e616d61 0x63655220 0x74697572 0x83dc5f00
|
||||||
|
0x614040: 0x557b1484 0x7e520297 0x63603e62 0x65579bcb
|
||||||
|
>>> x/x $rax+0x8
|
||||||
|
0x614018: 0x00000800
|
||||||
|
```
|
||||||
|
|
||||||
|
You will begin to notice that $rax+0x8 is the coordinate you entered while $rbp-0x58 is the hardcorded coordinates in the map data.
|
||||||
|
|
||||||
|
|Code|Coord|
|
||||||
|
| --- | --- |
|
||||||
|
|0x1| A1 |
|
||||||
|
|0x2| A2 |
|
||||||
|
|0x4| A3 |
|
||||||
|
|0x8| A4 |
|
||||||
|
|0x10| A5 |
|
||||||
|
|0x20| A6 |
|
||||||
|
|0x40| A7 |
|
||||||
|
|0x80| A8 |
|
||||||
|
|
||||||
|
|0x100| B1 |
|
||||||
|
|0x200| B2 |
|
||||||
|
|0x400| B3 |
|
||||||
|
|0x800| B4 |
|
||||||
|
|0x1000| B5 |
|
||||||
|
|0x2000| B6 |
|
||||||
|
|0x4000| B7 |
|
||||||
|
|0x8000| B8 |
|
||||||
|
|
||||||
|
|0x10000| C1 |
|
||||||
|
|0x20000| C2 |
|
||||||
|
|0x40000| C3 |
|
||||||
|
|0x80000| C4 |
|
||||||
|
|0x100000| C5 |
|
||||||
|
|0x200000| C6 |
|
||||||
|
|0x400000| C7 |
|
||||||
|
|0x800000| C8 |
|
||||||
|
|
||||||
|
|0x1000000| D1 |
|
||||||
|
|0x2000000| D2 |
|
||||||
|
|0x4000000| D3 |
|
||||||
|
|0x8000000| D4 |
|
||||||
|
|0x10000000| D5 |
|
||||||
|
|0x20000000| D6 |
|
||||||
|
|0x40000000| D7 |
|
||||||
|
|0x80000000| D8 |
|
||||||
|
|
||||||
|
|0x100000000| E1 |
|
||||||
|
|0x200000000| E2 |
|
||||||
|
|0x400000000| E3 |
|
||||||
|
|0x800000000| E4 |
|
||||||
|
|0x1000000000| E5 |
|
||||||
|
|0x2000000000| E6 |
|
||||||
|
|0x4000000000| E7 |
|
||||||
|
|0x8000000000| E8 |
|
||||||
|
|
||||||
|
|0x10000000000| F1 |
|
||||||
|
|0x20000000000| F2 |
|
||||||
|
|0x40000000000| F3 |
|
||||||
|
|0x80000000000| F4 |
|
||||||
|
|0x100000000000| F5 |
|
||||||
|
|0x200000000000| F6 |
|
||||||
|
|0x400000000000| F7 |
|
||||||
|
|0x800000000000| F8 |
|
||||||
|
|
||||||
|
|0x1000000000000| G1 |
|
||||||
|
|0x2000000000000| G2 |
|
||||||
|
|0x4000000000000| G3 |
|
||||||
|
|0x8000000000000| G4 |
|
||||||
|
|0x10000000000000| G5 |
|
||||||
|
|0x20000000000000| G6 |
|
||||||
|
|0x40000000000000| G7 |
|
||||||
|
|0x80000000000000| G8 |
|
||||||
|
|
||||||
|
|0x100000000000000| H1 |
|
||||||
|
|0x200000000000000| H2 |
|
||||||
|
|0x400000000000000| H3 |
|
||||||
|
|0x800000000000000| H4 |
|
||||||
|
|0x1000000000000000| H5 |
|
||||||
|
|0x2000000000000000| H6 |
|
||||||
|
|0x4000000000000000| H7 |
|
||||||
|
|0x8000000000000000| H8 |
|
||||||
|
|
||||||
|
### Updating the seed 4030AF ###
|
||||||
|
|
||||||
|
Here is where the seed manipulation is happenning:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
It takes the coordinates and uses this to update the initial seed. If you were to input **B4**: B being x and 4 being y.
|
||||||
|
|
||||||
|
```
|
||||||
|
seed = init_seed + ((y*0x593) + (x*0x1E01) + (x * y + 0x14a1)) & 0xffffffffffffffff
|
||||||
|
```
|
||||||
|
|
||||||
|
Once you have decoded the last level it will ask you to combine all the letters that were created from the coordinates. The hint here is the number **13** hidden between the PEWs.
|
||||||
|
|
||||||
|
```
|
||||||
|
Aye!PEWYouPEWfoundPEWsomePEWlettersPEWdidPEWya?PEWToPEWfindPEWwhatPEWyou'rePEWlookingPEWfor,PEW
|
||||||
|
you'llPEWwantPEWtoPEWre-orderPEWthem:PEW9,PEW1,PEW2,PEW7,PEW3,PEW5,PEW6,PEW5,PEW8,PEW0,PEW2,PEW3,PEW5,PEW6,PEW1,PEW4.PEWNextPEWyouPEWletPEW13PEWROTPEWinPEWthe
|
||||||
|
PEWsea!PEWTHEPEWFINALPEWSECRETPEWCANPEWBEPEWFOUNDPEWWITHPEWONLYPEWTHEPEWUPPERPEWCASE.
|
||||||
|
```
|
||||||
|
|
||||||
|
You will need to shuffle around the letters and use ROT13 to decode them.
|
||||||
|
OHGJURERVFGUREHZ -> BUTWHEREISTHERUM
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Here is the code used to decode the pewpew map data:
|
||||||
|
|
||||||
|
```
|
||||||
|
import struct
|
||||||
|
import hexdump
|
||||||
|
|
||||||
|
|
||||||
|
pewmap = [[0x1, "A1"], [0x2, "A2"], [0x4, "A3"], [0x8, "A4"], [0x10, "A5"], [0x20, "A6"], [0x40, "A7"], [0x80, "A8"],
|
||||||
|
[0x100, "B1"], [0x200, "B2"], [0x400, "B3"], [0x800, "B4"], [0x1000, "B5"], [0x2000, "B6"], [0x4000, "B7"], [0x8000, "B8"],
|
||||||
|
[0x10000, "C1"], [0x20000, "C2"], [0x40000, "C3"], [0x80000, "C4"], [0x100000, "C5"], [0x200000, "C6"], [0x400000, "C7"], [0x800000, "C8"],
|
||||||
|
[0x1000000, "D1"], [0x2000000, "D2"], [0x4000000, "D3"], [0x8000000, "D4"], [0x10000000, "D5"], [0x20000000, "D6"], [0x40000000, "D7"], [0x80000000, "D8"],
|
||||||
|
[0x100000000, "E1"], [0x200000000, "E2"], [0x400000000, "E3"], [0x800000000, "E4"], [0x1000000000, "E5"], [0x2000000000, "E6"], [0x4000000000, "E7"], [0x8000000000, "E8"],
|
||||||
|
[0x10000000000, "F1"], [0x20000000000, "F2"], [0x40000000000, "F3"], [0x80000000000, "F4"], [0x100000000000, "F5"], [0x200000000000, "F6"], [0x400000000000, "F7"], [0x800000000000, "F8"],
|
||||||
|
[0x1000000000000, "G1"], [0x2000000000000, "G2"], [0x4000000000000, "G3"], [0x8000000000000, "G4"], [0x10000000000000, "G5"], [0x20000000000000, "G6"], [0x40000000000000, "G7"], [0x80000000000000, "G8"],
|
||||||
|
[0x100000000000000, "H1"], [0x200000000000000, "H2"], [0x400000000000000, "H3"], [0x800000000000000, "H4"], [0x1000000000000000, "H5"], [0x2000000000000000, "H6"], [0x4000000000000000, "H7"], [0x8000000000000000, "H8"]]
|
||||||
|
size = 0x240
|
||||||
|
seed = 0x3b1ee5f6b3d99ff7
|
||||||
|
|
||||||
|
def gen_seed(seed):
|
||||||
|
seed = ((seed * 0x41C64E6D) + 0x3039) & 0xFFFFFFFFFFFFFFFF
|
||||||
|
return seed
|
||||||
|
|
||||||
|
|
||||||
|
with open("referenced_data.bin", "rb") as fp:
|
||||||
|
data = fp.read()
|
||||||
|
dst = ""
|
||||||
|
i = 0
|
||||||
|
while i < len(data):
|
||||||
|
k = 0
|
||||||
|
while k < size and (k+i) < len(data):
|
||||||
|
seed = gen_seed(seed)
|
||||||
|
buff = data[k+i]
|
||||||
|
dst = dst + chr((ord(buff) ^ (seed & 0xff)) & 0xff)
|
||||||
|
k = k + 1
|
||||||
|
print "old_seed: %s" % hexdump.dump(dst[16+i:24+i])
|
||||||
|
seed_int = struct.unpack("<Q", dst[16+i:24+i])[0]
|
||||||
|
print_coords = ""
|
||||||
|
for coordinates in pewmap:
|
||||||
|
coords = struct.unpack("<Q", dst[i:8+i])[0]
|
||||||
|
result = coords & coordinates[0]
|
||||||
|
|
||||||
|
while result != 0x0:
|
||||||
|
if result == 0x1:
|
||||||
|
result = result + 0x1
|
||||||
|
result = result & 0x1
|
||||||
|
result >> 0x1
|
||||||
|
|
||||||
|
print_coords = print_coords + " " + coordinates[1]
|
||||||
|
x = ord(coordinates[1][0])
|
||||||
|
y = ord(coordinates[1][1])
|
||||||
|
seed_int = (seed_int + ((y * 0x593) + x * 0x1E01) + (y * x + 0x14a1)) & 0xFFFFFFFFFFFFFFFF
|
||||||
|
seed = seed_int
|
||||||
|
print "coordinates: ", print_coords
|
||||||
|
print "new_seed: ", hexdump.dump(struct.pack('<Q', seed))
|
||||||
|
dst = dst[:16+i] + struct.pack('<Q', seed) + dst[24+i:]
|
||||||
|
print dst[i:400+i]
|
||||||
|
print "\n"
|
||||||
|
i += size
|
||||||
|
open("output.bin", "wb").write(dst)
|
||||||
|
```
|
||||||
|
|
||||||
|
[Challenge 4 <- Back](https://securedorg.github.io/flareon4/challenge4) | [Next -> Challenge 6](https://securedorg.github.io/flareon4/challenge6)
|
||||||
@@ -23,7 +23,7 @@ You can download the binaries [HERE](https://github.com/securedorg/securedorg.gi
|
|||||||
|
|
||||||
### Challenge 4) [notepad.exe](https://securedorg.github.io/flareon4/challenge4) ###
|
### Challenge 4) [notepad.exe](https://securedorg.github.io/flareon4/challenge4) ###
|
||||||
|
|
||||||
### Challenge 5) [pewpewboat.exe](https://securedorg.github.io/flareon4/challenge5) *pending* ###
|
### Challenge 5) [pewpewboat.exe](https://securedorg.github.io/flareon4/challenge5) ###
|
||||||
|
|
||||||
### Challenge 6) [payload.dll](https://securedorg.github.io/flareon4/challenge6) *pending* ###
|
### Challenge 6) [payload.dll](https://securedorg.github.io/flareon4/challenge6) *pending* ###
|
||||||
|
|
||||||
|
|||||||
BIN
flareon4/images/ch5_andcoords.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
flareon4/images/ch5_decode.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
flareon4/images/ch5_diagram.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
flareon4/images/ch5_finale.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
flareon4/images/ch5_gdb.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
flareon4/images/ch5_innerdecode.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
flareon4/images/ch5_parsedmap.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
flareon4/images/ch5_patch.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
flareon4/images/ch5_registers.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
flareon4/images/ch5_run.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
flareon4/images/ch5_seedmanip.png
Normal file
|
After Width: | Height: | Size: 40 KiB |