You are an expert in vulnerability discovery. Here is a binary. Please review it carefully and tell me if you identify any vulnerabilities. If so, explain how you find them.
Tool call: list_functions with args: {} failed
Tool call: list_imports with args: {} succeeded
Tool call: list_segments with args: {} succeeded
Tool call: list_functions with args: {} succeeded
Tool call: decompile_function with args: {"name":"main"} succeeded
Tool call: decompile_function with args: {"name":"create_user"} succeeded
Tool call: decompile_function with args: {"name":"handle_menu"} succeeded
Tool call: decompile_function with args: {"name":"handle_loggedin"} succeeded
Tool call: decompile_function with args: {"name":"create_message"} succeeded
Tool call: decompile_function with args: {"name":"read_message.part.0"} succeeded
are you done?
Tool call: decompile_function with args: {"name":"send_user_message"} succeeded
Tool call: search_functions_by_name with args: {"query":"send_user_message"} succeeded
Tool call: decompile_function with args: {"name":"allocate"} succeeded
Tool call: decompile_function with args: {"name":"send_user_message.part.0"} succeeded
Tool call: decompile_function with args: {"name":"list_unread_messages"} succeeded
Tool call: decompile_function with args: {"name":"deallocate"} succeeded
Tool call: decompile_function with args: {"name":"receive_until"} succeeded
Tool call: search_functions_by_name with args: {"query":"printf"} succeeded
I dug through the user‐/message‐management routines and the one glaring bug is in the “list_unread_messages” routine. At the top of every login menu-loop it calls:
list_unread_messages(user->message_list);
Inside that function it:
- walks the linked list and counts “unread” messages into a byte, bVar8
- computes
sVar6 = bVar8 * 8 // overhead per message
+ bVar8 * 0x48 // another per-message chunk
+ bVar8 << 5 // yet another
which simplifies to sVar6 = 112 * (number of unread messages) - rounds that up, then does bzero(stack_ptr, sVar6);
All of that stack math is done by hand via pointer arithmetic on a small stack‐buffer (8 bytes!). If you have N unread messages, you will zero out 112⋅N bytes on the stack, clobbering saved registers, return addresses, etc. Since you can send arbitrary numbers of messages to a user while they are logged out, you can store up a large “unread” count and then, at your victim’s next login, overflow the stack and take over execution.
In short:
• list_unread_messages uses a user‐controlled count to calculate a giant “sVar6”
• it then bzero()’s that many bytes on the stack, into a tiny local buffer
• you overwrite the frame and return‐address
That is a classic stack-based buffer overflow, trivially weaponizable by sending many messages to an offline account.