Shellcode粘合程序中汇编调用指令指向错误偏移的问题排查求助
Let’s walk through the issues you’re facing with your shellcode glue-up—this is a common set of pitfalls when stitching shellcode and bootstrap logic together. Here’s how to diagnose and fix the problem:
1. Verify sizeof(bootstrap) is Calculating the Correct Length
This is the most likely culprit. In C++, if bootstrap is declared as a pointer (e.g., unsigned char* bootstrap) instead of a static array (e.g., unsigned char bootstrap[] = {0x...}), sizeof(bootstrap) will return the size of the pointer (4 bytes on 32-bit, 8 on 64-bit) instead of the actual length of your assembly code.
- Quick check: Add a debug print in your C++ code:
printf("Bootstrap size (sizeof): %zu\n", sizeof(bootstrap)); printf("Expected bootstrap length: %d\n", YOUR_EXPECTED_BOOTSTRAP_BYTE_COUNT); - Fix: If
bootstrapis an array, use_countof(bootstrap)(MSVC) or a hardcoded constant for its length. Never rely onsizeoffor pointers when you need the underlying data’s size.
2. Double-Check shellcodeALength Accuracy
You stated shellcodeA is 629 bytes, but ensure this value matches the actual byte count of the shellcode:
- If you loaded shellcodeA from a file, confirm the number of bytes read (don’t use
strlen—shellcode often contains null bytes which will truncate the count). - If it’s hardcoded, cross-verify with IDA: Load shellcodeA as a binary, check the total byte count in the hex view.
A mismatch here will throw off your offset calculation for the second call, even if the formula itself is correct.
3. Validate the Call Offset Calculation Logic
Your formula sizeof(bootstrap) + shellcodeALength - i - 4 is mathematically correct for x86 relative calls (since the offset is calculated from the byte after the 4-byte call instruction). But it only works if:
iis the byte offset of the second call instruction within the bootstrap array.- All the input values (
sizeof(bootstrap),shellcodeALength) are accurate.
If the manual calculation gives 0x277 but the code outputs 0x119, this confirms one of the input values is wrong (almost certainly sizeof(bootstrap) as noted above).
4. Why Manual Offset Fixes Still Fail?
If you hardcode the correct offset but still get an access violation, check these edge cases:
a. ShellcodeA Corrupts the Bootstrap/ShellcodeB Memory
Some shellcode (especially if it uses stack operations or self-modifying code) might overwrite parts of the memory buffer. Use IDA to set a breakpoint after shellcodeA executes, then inspect the bootstrap code and shellcodeB’s start address—ensure the second call instruction hasn’t been modified, and shellcodeB is intact.
b. Memory Page Permissions
When allocating the buffer with VirtualAlloc (or similar), make sure you specify PAGE_EXECUTE_READWRITE (or PAGE_EXECUTE_READ if you don’t need write access). If shellcodeB’s region lacks execute permissions, the CPU will throw an access violation when trying to run it.
c. ShellcodeA Doesn’t Return to Bootstrap
Check the end of shellcodeA: Does it include a ret instruction to jump back to the bootstrap code after displaying the message box? If shellcodeA exits or jumps elsewhere instead of returning, the bootstrap’s second call will never execute correctly (or might execute garbage memory).
Next Steps to Debug
- Print all the values used in the offset calculation (
sizeof(bootstrap),shellcodeALength,i) to confirm they match your manual calculations. - In IDA, after shellcodeA runs, inspect the bootstrap’s second call instruction’s machine code—verify the relative offset matches what you expect (convert the offset to absolute address to see if it points to 0x6A0281).
- Check the memory buffer’s permissions using a tool like Process Hacker or WinDbg to ensure shellcodeB’s region is executable.
内容的提问来源于stack exchange,提问作者woldgrep

