wk4 - structs, protocols, stripped binary
Theme: Structs, protocols, stripped binaries
Reminders
Don't assume what functions do!
Look at manual for: parameters AND return values
Stripped (50)
Given
"Hey friend, can you tell me your favorite fruit?"
Solve
Input the favorite fruit which is "Golana Melon" as declared in the compiled binary. We enter the second stage, and we need to enter a second input correctly. This second input gets passed to a sys_open call, then this returned file descriptor gets read and we get the flag. So the second input should be the filename, which we know is "flag.txt". Enter and obtain flag.
Rudimentary data protocol (100)
Solve
Part 1: Scope out the program using Binja
Within main, there is a do-while loop, after which is the flag function. The only way to run flag function is if we exit the do-while loop, which requires i = 0. In turn, this requires process_packet() to return 1 because 1 XOR 1 gives 0.
Part 2: Look into process_packet() and check_packet()
Inside is a function called check_packet(). It seems this is the only place where process_packet() can return a value that is not zero. This means we want check_packet to eventually return 1.
In process_packet(), we are first malloc-ing an object on the heap of size 0xc bytes. Then, we ask for user input, and by an intricate sequence of action, different chars of user input get assigned to different bytes of the heap object.
The user input must not be zero bytes and its first char must equal to the number of bytes read. We should send at least 3 bytes. Treat these as general requirements that our input must fulfill every time. check_packet() only gets called if the address of one byte past a temp pointer (initially points to second char of user input) is greater than or equal to the byte immediately after the last byte of user input.
For check_packet() to return 1, we must (1) set connected to 1, (2) set valid_msg to 1 and lastly (3) let second char of heap object have value = 2 such that check_packet() returns 1. Let's break down step (1),(2) and (3).
For step (1), we want to directly call check_packet(). The second byte of heap object should be \x00 such that connected is set to 1 within check_packet(). A possible payload is: b'\x03\x00\x04'.
For step (2), the goal is for the 2nd byte of the heap object to equal 0x01, and the 9th byte to be 0x37.
In order to set the 9th byte of heap object, we must first NOT call check_packet inside of the while loop in process_packet(), and trickle down to the last condition where the fourth char of user input gets assigned to heap obj's 9th byte. Then, the temp pointer points to the 5th byte of user input, the second byte of heap object gets assigned the 5th char of user input and we enter another iteration of the while-loop. Do another iteration, trickling down to the same last condition where the 7th char of user input gets assigned to 9th byte of heap object. Temp pointer updates to point to the byte after the last byte read from user input, and we enter check_packet to actually set valid_msg to 1.
The payload's 5th byte should be 0x01 because that after all this, it gets assigned to the heap object's second byte, which we can treat as an "instruction code". We need 0x01 for instruction code to set valid_msg to 1. Payload's 7th byte should be 0x37 because that gets assigned to the heap object's 9th byte, which needs to be 0x37 to successfully set check_packet.
One possible payload is: b'\x07\x01\x00\x00\x01\x00\x37'.
Lastly, in step (3), we want to call check_packet() such that this function returns 1. The 2nd byte of the heap object needs to be 0x02 to achieve this, which means our input's 2nd character should be 0x02. One possible payload is: b'\x03\x02\x00'.
After entering three payloads, we get the flag!
Last updated