type
status
date
slug
summary
tags
category
icon
password
In this blog, we'll explore how to insert a simple Windows API
MessageBox
to a PE-format executable before it starts.Step 1: Locating the MessageBoxA Function Address
Our journey begins with finding the address of the
MessageBoxA
function in the virtual memory during runtime, here I used x86dbg, a powerful x86/x64 debugger. The address I found for my application is 0x76B28270
, please note that this address isn't fixed and may change after a reboot. To find the address in x86dbg, use this command:
Step 2: View the Text Section Header in the PE File
The text section of the PE file, which is executable by default, will house our new code. So, let's seek an empty space within this section for our
MessageBox
.In this demonstration, I used a open sourced PE tool to view the
text
section header in the PE header. The memory block for the code section in my application spans from 0x400
to 0x400 + 0xFA00
. Our code can be put in any empty space within this block. For this blog, assume 0xFC80
as the starting position of the code we insert.Step 3: Implementing the Message Box to Insert
For this blog, we'll simply create an empty message box via the Windows API
MessageBox
, then return to the original entry point of our application. The original entry point of my application is 0x11028
, and my image base is 0x400000
. You can also retrieve this information from the PE optional header using your preferred PE tool.Here's the code we're going to inject: we push all the arguments into the stack frame, call the
MessageBoxA
function, then jump back to the original entry point when it returns. Note that MessageBoxA
is one of the Windows API and it follows the stdcall
calling convention, which means the function callee is responsible for cleaning up the stack before it returns.Step 4: Understanding CALL
and JMP
Instructions
Before we proceed, it's crucial to understand that the
CALL
and JMP
instructions within the same EXE/DLL calculate the target address using a relative addressing mode. The Effective Address (EA) is computed using the formula:- The
Next Instruction Address
is the address immediately succeeding theCALL
orJMP
instruction.
- The
Relative Offset
is the value provided with theCALL
orJMP
instruction.
Why do such instructions using relative addressing mode? Relative addressing refers to specifying an address relative to the current position in code (often relative to the next instruction). This way, if the entire code block gets moved in memory, as it often does when a DLL or an EXE gets loaded, the relative addresses stay valid without requiring any modifications, because they still point to the same place relative to the rest of the code.
Step 5: Calculating the Relative Offset
Now that we're familiar with the effective address, we need to calculate the relative offset that goes into the hardcoding of the instruction. Keep in mind, the address where we inserted our code in the text section is
0xFC80
. However, this is the offset of our code in the file buffer, and we need to compute the actual address our code would have during runtime. The formula is:Note that the virtual offset of text section has been found in step 2.
Finally, we can now calculate the relative offset for the
CALL
and JMP
instructions:For the
CALL
instruction:For the
JMP
instruction:There you go! Now you can put the binary hardcode we computed in step 3-5 into the PE file using your favorite hex editor (I used WinHex).
Step 6: Updating the Entry Point in the PE Header
After injecting our code, we also need to modify the entry point field in the PE header to point to our newly added code. This field tells the operating system where to start executing code when the program is launched.
You may also want to disable ASLR flag in DLL characteristics, this technique randomizes the image base every time the application starts:
Step 7: We did it!
With the final modification, you've successfully added a new
MessageBox
to your executable file. Launch your application, and you should be greeted with an empty message box before the original program starts.Step 8: Automate the Process with C++
Now let’s re-do all the steps above, but this time we will do it with C++, note that I used some utility functions & classes in the code below, the implementation of these functions are irrelevant.
- 作者:Zack Yang
- 链接:https://zackyang.blog/article/add-message-box-to-any-executable
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章