Intro
We have a network traffic capture and we have to figure out the files being transferred.
Write-Up
We see that there are 2 streams in this capture. It is network traffic between the following devices.
xn--zn8hscq4eeafedhjjkl.flare-on.com = 🐈😸😻😹😺🐱😼🙀😿😾😽😻.flare-on.com
xn--zn8hrcq4eeadihijjk.flare-on.com = 😺😸😹😻😼😽🙀😿😾🐱🐈.flare-on.com
The first stream is something like below
00000000 4d 45 30 57 32 00 00 00 32 00 00 00 7e 6d 65 6f ME0W2... 2...~meo
00000010 77 7e 20 28 3d 5e 2e 5e 3d 29 20 7e 6d 65 6f 77 w~ (=^.^ =) ~meow
00000020 7e 2e 2e 2e 2e 20 63 61 6e 20 68 61 7a 20 4d 65 ~.... ca n haz Me
00000030 65 6f 6f 6f 77 77 77 4d 65 6d 65 3f 3f 3f eooowwwM eme???
00000000 4d 45 30 57 d0 24 0a 00 d0 24 0a 00 89 50 4e 47 ME0W.$.. .$...PNG
00000010 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 05 d8 ........ IHDR....
00000020 00 00 04 62 08 06 00 00 00 b7 69 95 af 00 00 0c ...b.... ..i.....
00000030 63 69 43 43 50 49 43 43 20 50 72 6f 66 69 6c 65 ciCCPICC Profile
00000040 00 00 48 89 95 57 07 5c 93 47 1b bf 77 64 92 b0 ..H..W.\ .G..wd..
If we extract the reply, we get the cat picture. We analyze the PNG file but it doesn’t have anything extraordinary. We check the second stream and we see the following.
00000000 4d 45 30 57 8b 00 00 00 b4 00 00 00 50 41 33 30 ME0W.... ....PA30
00000010 f0 5e 21 03 77 a0 d7 01 18 23 c0 b2 9f 0b 01 01 .^!.w... .#......
00000020 7a 02 96 07 13 26 5c 39 70 63 c4 90 b3 7a 49 4c z....&\9 pc...zIL
00000030 68 32 e6 c0 89 9d 72 31 3c 19 b0 e7 42 8f 03 6d h2....r1 <...B..m
00000040 b9 1a 65 ca 93 ad 4a a3 76 79 22 0c e8 15 c2 81 ..e...J. vy".....
00000050 2b 17 ae f4 58 d0 65 a9 5c 3e 1b 39 72 b5 6a 97 +...X.e. \>.9r.j.
00000060 af 46 2e 2f 7a 6c b8 33 e2 42 83 25 47 b9 42 68 .F./zl.3 .B.%G.Bh
00000070 d0 e5 ca 88 2b 33 da 74 18 d1 94 a9 5e 29 1f da ....+3.t ....^)..
00000080 b4 d5 73 67 c2 80 3e 6d 6e 72 2f 9a ce 47 cd 91 ..sg..>m nr/..G..
00000090 11 6b d9 1f a1 2e ab c2 b4 8b 96 74 6a 2e a2 69 .k...... ...tj..i
000000A0 71 a3 c1 55 b4 68 06 ec e8 70 fe 58 25 4a e1 44 q..U.h.. .p.X%J.D
000000B0 ff 22 a5 30 fa a8 69 70 56 d9 01 00 80 d2 3e 03 .".0..ip V.....>.
00000000 4d 45 30 57 09 00 00 00 27 00 00 00 50 41 33 30 ME0W.... '...PA30
00000010 d0 84 49 07 77 a0 d7 01 18 23 c0 b2 9f 0b 01 01 ..I.w... .#......
00000020 46 00 94 13 53 1a cc 38 d1 31 a0 d7 78 07 00 00 F...S..8 .1..x...
00000030 52 fd 0c R..
So we see that server and client communicates with PA30
header. When we google this string we see that this is a format to distribute Microsoft Delta patches.
When we Google this format, we can find this repository Let’s apply our first patch with delta_patch.py
to our png file.
We get our first DLL file. When we decompile this DLL, we can see that after it sends or receives packages, it xors the result.
loc_10001155:
xor edx, edx
mov [ebp+Dst], 5
mov eax, ecx
div [ebp+Dst]
mov al, byte ptr ds:aMeoow[edx] ; "meoow"
xor [ebx+ecx], al
inc ecx
cmp ecx, esi
jb short loc_10001155
We can either emulate the traffic between the host and client or we can just apply the patches, xor the result and search for the flag. I will do the second one. I exported pcapng
file to JSON file with Wireshark and analyzed the traffic.
from ctypes import (windll, wintypes, c_uint64, cast, POINTER, Union, c_ubyte,
LittleEndianStructure, byref, c_size_t)
import zlib
import json
import struct
# types and flags
DELTA_FLAG_TYPE = c_uint64
DELTA_FLAG_NONE = 0x00000000
DELTA_APPLY_FLAG_ALLOW_PA19 = 0x00000001
# structures
class DELTA_INPUT(LittleEndianStructure):
class U1(Union):
_fields_ = [('lpcStart', wintypes.LPVOID),
('lpStart', wintypes.LPVOID)]
_anonymous_ = ('u1',)
_fields_ = [('u1', U1),
('uSize', c_size_t),
('Editable', wintypes.BOOL)]
class DELTA_OUTPUT(LittleEndianStructure):
_fields_ = [('lpStart', wintypes.LPVOID),
('uSize', c_size_t)]
# functions
ApplyDeltaB = windll.msdelta.ApplyDeltaB
ApplyDeltaB.argtypes = [DELTA_FLAG_TYPE, DELTA_INPUT, DELTA_INPUT,
POINTER(DELTA_OUTPUT)]
ApplyDeltaB.rettype = wintypes.BOOL
DeltaFree = windll.msdelta.DeltaFree
DeltaFree.argtypes = [wintypes.LPVOID]
DeltaFree.rettype = wintypes.BOOL
#xor the traffic
def xor(data):
key = bytearray('meoow','utf-8')
l = len(key)
result = bytearray((
(data[i] ^ key[i % l]) for i in range(0,len(data))
))
return result
def apply_patchfile_to_file(inbuf, patch_contents):
buf = cast(bytes(inbuf), wintypes.LPVOID)
buflen = len(inbuf)
# some patches (Windows Update MSU) come with a CRC32 prepended to the file
# if the file doesn't start with the signature (PA) then check it
if patch_contents[:2] != b"PA":
paoff = patch_contents.find(b"PA")
if paoff != 4:
raise Exception("Patch is invalid")
crc = int.from_bytes(patch_contents[:4], 'little')
patch_contents = patch_contents[4:]
if zlib.crc32(patch_contents) != crc:
raise Exception("CRC32 check failed. Patch corrupted or invalid")
applyflags = DELTA_FLAG_NONE
dd = DELTA_INPUT()
ds = DELTA_INPUT()
dout = DELTA_OUTPUT()
ds.lpcStart = buf
ds.uSize = buflen
ds.Editable = False
dd.lpcStart = cast(patch_contents, wintypes.LPVOID)
dd.uSize = len(patch_contents)
dd.Editable = False
status = ApplyDeltaB(applyflags, ds, dd, byref(dout))
if status == 0:
raise Exception("Patch failed")
buf = dout.lpStart
n = dout.uSize
outbuf = bytes((c_ubyte*n).from_address(buf))
DeltaFree(buf)
return outbuf
with open('dump.json') as r:
packets = json.load(r)
for packet in packets:
layers = packet['_source']['layers']
if 'data_raw' in layers:
raw_bytes = layers['data_raw'][0]
data_bytes = bytes.fromhex(raw_bytes)
patch_bytes = data_bytes[12:]
empty_bytes = bytearray(4096)
patched_bytes = apply_patchfile_to_file(empty_bytes,patch_bytes)
xored_bytes = xor(patched_bytes)
search = xored_bytes.find(bytes('@flare-on.com','utf-8'))
if (search != -1):
result = xored_bytes[search-50:search+50].decode('utf-8')
print(result)
break
When we run this script, we get the following flag
1m_H3RE_Liv3_1m_n0t_a_C4t@Flare-on.com
Flare-On 2021 Write-ups