32-bit Assembly IV, dry goods sharing, implementation of assembly injection, and number of fast-locating call APIs (OD view)
Yesterday, everyone may have read the code, do not know yesterday in the assembly code based on the implementation of the injection calculator.
If not, it will be explained today, but it is recommended to familiarize yourself with the code yesterday (the course is closely followed, please do not pull any day, because today's knowledge,
may be linked to yesterday's knowledge, yesterday's knowledge, and the day before yesterday's hook ..., of course, if you know the assembly, not a novice, then you can directly look down.
One, remote thread injection, and assembler remote injection differences
Yesterday's code, you may have seen (not see also no relationship, is the remote thread injected code, development perspective, and assembly code injection, the bottom angle of two code)
Here, the difference between them
First of all, we know that any injection method has a specific situation in which they are used
1. Remote Thread Injection
This is only for software protection against low-use, the virus rarely use this, why
We know that remote thread injection, which creates a remote thread that will load our DLL, may not prevent you from using the CreateRemoteThread function for a protected program, but can target your DLL, such as traversing the number of DLLs
If you find one more, the program exits. Wait.
2. Remote injection of the Assembly
Assembly of the remote injection, this is a bit hard, why, because you write not a DLL, but a broken assembly code, write to the opposite memory, let him go to execute, so unless the opposite software, try to detect the memory state, otherwise it is not easy to detect the exception of their program
Of course, the assembly of remote injection, or will open up memory, but we know that the injection method of many kinds, we can play the imagination, only the sword, we can think, you do not want to apply for memory, we can not apply for memory, the opposite program will definitely save and align the problem
, for example, in order to ensure alignment, the opposite program will definitely be filled with NOP instructions, then we can use this memory, so that software, unless also detect NOP, and alignment, otherwise you inject into the opposite also found not, such as the opposite software is very strong, detection is in place, the bad to
Alignment is also detected, then we can put the opposite stack of memory elevation, our program code to write, the opposite is always not pay attention to test stack bar, the execution of our code out of the stack, the opposite is not possible to detect the stack in and out. So heavy in the imagination (nonsense a bit more, you can omit to look directly below:))
3. Assembly Remote Injection Code analysis (0D analysis)
Yesterday we because of time relations, did not specifically analyze yesterday's code, today we use OD (olleydbg) Step by step analysis,
This analysis also allows us to quickly grasp the debugging skills
① Analysis FindWindow, see what the assembler code does
First put out our code of yesterday
invoke Findwindow,null,offset G_szwindowname, the second argument is a string of calculator mov ret. endif The above code logic: look for the calculator, return the calculator window handle, if successful, (return value by default put EAX in) if successful, continue down execution, if fail, Call Showlasterror to display an error message
OD analysis
This is our general FindWindow interface.
We look in the next window, see if we find it, find the window handle and put it in the eax.
We can see that the window has been found, and the window handle is already in the eax, so eax = = NULL is not established, then jump to the next command location execution, and the next command location, then began to call GetWindowThreadProcessId
②getwindowthreadprocessid, gets the ID of the process
First, the assembly code that corresponds to the pseudo-directive is viewed
Invoke GetWindowThreadProcessId, @hWnd, addr @dwPID
The code is simple, we know that when the function is called, the code is pushed from right to left, so the first one will push Dwpid, and the second will push the hWnd.
OD analysis
Because take a step to cut the picture is too troublesome, and affect everyone to watch, straight directly marking, each step to write, so that everyone's own debugging, do not understand the time to see my every step represents what meaning
First, I circled the code for every step of the execution.
1. Lea eax,[local,3] means I'm going to take the third local variable, which is the third local variable of the stack, and as we've said before, the local variable is ebp-xxx to get, and now it's a 32-bit assembly, so each register is 4 bytes, so the third local variable is-12, and the corresponding local variables
is the-c
The real code of this code is translated into a
Lea Eax,dword PTR Ss:[ebp-oxc] position, we can go to the stack to see what the ebp-c position is, notice here because I went down to the bottom
So we have obtained the value of the process PID, so it is 810, the default is 0, then what is the meaning of that, is to get ebp-c address
2. Obtain the address of EBP (assuming the address is 18ff44) then address to eax, and then eax into the stack,
3. Put our first local variable, that is, the value of Ebp-4, (40D40, because here is the bracket, so the content of the stack is obtained, and the above is not fetching content, because we use the LEA command)
4. Call GetWindowThreadProcessId, this time, because we put the second part of the EAX into the stack (EAX is EBX-C's stack address), so the PID obtained
Value will give the content of the corresponding stack address (what means: you provide the address of the local variable, that is, our previous ebp-c address, the operating system to obtain the value of PID, will be based on the address you give, the corresponding address inside the content modified, so the equivalent is a MOV DWORD ptr[18ff44], 810)
At this point, we can conclude that this getwindowthreadprocessid, the execution of the process
1. Get the address of the local variable first (ebp-c address, note, not value)
2. Press Stack
3. Get the value of the first parameter in the stack (note that the value in the stack address, not the stack address) is the handle of the last obtained window
4. Call GetWindowThreadProcessId, change the value of the corresponding stack address to our PID value (810), so we've got the PID value.
Assembly Code:
invoke Openprocess,process_all_access, FALSE, @dwPID mov @hProcess, eax . if eax = = NULL invoke showlasterrorret . endif
First, put the PID stack, then false (in the assembly is 0) to press the stack, and then the permissions stack (the permission is constant)
Finally, the process is opened, and if the process handle is successfully obtained, the return value is placed in the EAX and the EAX is given to the local variable
Then determine whether the local variable is ==null, do not want to wait to continue to go, equality is open failure, execute error code hint (showlasterror)
OD analysis
I don't have to talk about this place.
1. First, we put the PID of the process, that is, the local variable third (the value inside the Ebp-c) to press the stack
2. Then press the second argument from right to left, which is false
3. Then press-in permissions
4. Call OpenProcess
5. Success is eax the instance handle of the process is saved
6. Determine if EAX is equal to null, equality (acquisition failure) continues to execute, calling call injectas.0040118b
④VIRTUALALLOCEX, remote request memory
Assembly code
invoke VirtualAllocEx, @hProcess, NULL, 1000h, Mem_commit, Page_execute_readwrite mov @lpBuff, eax . if eax = = NULL invoke showlasterrorret . endif
This is the same as above, all from right to left into the stack, if successful, returns the first address of the memory requested by the remote process, placed in the EAX
Failure is judged below.
OD analysis (note that the above has been analyzed many times, API call of the parameter, out of the stack, and register to the local variable assignment)
So below the API I will provide pictures to see, but not the specific analysis, are the same, if you are interested, you can practice practiced hand, manual analysis, see the code flow how to execute.
Has succeeded, will certainly execute, and now introduce the second usage of OD
When an application is opened, we can choose an additional way to hang the program
Now we attach the computer to see if this place has applied for memory
Re-open OD, now two OD
, choose our Calculator program
Search us with Vir ... Apply for successful memory first address to see if the application is successful
The application succeeds, and then we proceed to the next instruction to execute, write the memory data into this face
⑤, use WriteProcessMemory to write memory data into the face.
Note that we write the binary of the code that makes our Inject_code, so the program when calling the remote thread,
will run our binary as code.
Look at the assembly code:
Invoke WriteProcessMemory, @hProcess, @lpBuff, inject_code, start-inject_code, NULL
Pass the argument, what do not say, here need to notice what to write is the memory we just requested the first address
Now is the lpbuff, that is, where we write, (to the computer we apply for which block of memory to write, so Lpbuff is the first address of the calculator this memory)
The data written is a binary of the Inject_code code
The size of the write is the size of the Start-inject_code data
Inject_code is on the top of the start label, we look at
assembly code, and OD analysis
OD analysis
Can see that my label
1. Indicates that we want to write to the starting address of the opposite memory (that is, we apply with Vir)
2. We are going to write the buffer, that is, I'm going to write inject as the beginning, start to write this memory
3. The size of the write is the start-inject_code we calculated.
4. Actual bytes Written We don't care, about Start-inject_code we look at the code and start to understand.
Equivalent to 00401017-00401000 = 17 bytes, so write 17 bytes
Look at the computer program, there is no binary code written to us
Exactly 17 bytes, and the code is written in.
Finally, we call Createreomtethread to begin to execute the Inject_code as code, where the reference is the same as above
Not in the analysis.
At this point, the analysis here to the end, the following code is not analyzed, the beginning of the real code to write assembly of the program, because the assembly code and the above are called API, and then the API. Save the return value to the local variable, the stack and so on are the same, so the bottom of the real write. If the perceptual zone, Want to improve their debugging ability, as well as the proficiency of OD, you can analyze
Second, compilation of injection code, and should pay attention to the various issues
First of all, if you have done yesterday homework students should know, will encounter the opposite code and our code location is not the same
Like what
The location of our inject_code, and the opposite Inject_code code
There is also a DLL in the location of the different, it will affect the call of the API
For example, our code calls a MessageBox inside the Inject_code, and he can pop the window.
But notice that this is going to go wrong on the opposite side, why
So we need to pay attention to a few questions
1.Call when the problem
2. Address relocation problem
First of all, 1 questions.
The problem of ①call.
Let's look at a call in the assembly code and press the SPACEBAR to see what the assembly is
We separately in our own program's Inject_code and opposite program's inject_code to see the execution MessageBox what will appear the problem
This is the assembly code.
Look at the OD.
We can see that all calls are 0x401204, but is the result correct?
We used the Disassembly window CTRL + G to jump to 00401204 we found
The first program, that is, our injection program, it calls the MessageBox, is there
While the calculator program calls, there is no, can't find this memory, so it went wrong
Why this problem, this is the famous relocation problem, the previous time we DLL injection, is the system to help us reposition the
And now we're going to reposition the problem ourselves.
First we know that any program running, will be added to the Ntdll, and Kernel32.dll will also load, User32.dll will also load
The Kernel32.dll does not have to be loaded, but the%99.999 program loads the DLL ((*^▽^*))
User32.dll is related to the user, there will also be%99 loading
Then there is a problem, see
We inject the program call MessageBox to find the address of the MessageBox from User32.dll and call
and the B program, obviously the first address of the DLL is 2000 position, first don't say we can call it
Just as we were looking at call, he was directly call a constant 00401204, and obviously, this memory is not part of the B process, so it went wrong.
He's a part of a process,
So we're going to reposition the API address.
How to locate
1. Get the loaded instance handle of the User32.dll of the current injection program
2. and create a process snapshot traverse the instance handle of the machine process module User32.dll
and see
First the injection program to get 1000h, the remote program gets the User32.dll module address is 2000h
3. Get the MessageBox distance module offset, note that this offset is obtained, is the same as the two sides, because the function is the same position, only
Module address is not loaded in the same location
Look at the picture
It's all 100, so we have a formula.
First address of function-the first address of the module = The actual offset of the functional distance module is obtained
Then the remote module + function distance module actual offset, the remote process to obtain the actual offset of the MessageBox
Assuming our local process is 1000h, the distance from the MessageBox is 1100.
Then 1100 (the first address of the function)-the first address of the module (1000) = actual offset (100)
Then the remote Module address (2000) + actual offset (100) = actual function address
This formula please be familiar with remembering
Look at the words do not understand, look at the picture:
Look at the formula first, then the arrow pointing
So, based on this formula, we're going to start writing our assembler code.
Now the function address redefinition problem has been solved, but note that only the relocation of the function address
After writing the assembly code, it is clear that another function calls the address-independent relocation problem,
That's the second question we're going to solve, saying a little bit more, look at the code, actually the code is simple.
LOCAL@hLocalUser32Module:MODULE;module address to store local User32.dllLOCAL@hRemoteUser32Module:MODULE;module address for storing remote user32.dll;1. Call GetModule load User32.dll to get user32.dll module addressInvoke Getmodule,offset G_szuser32;G_szuser32 As String user32.dll, that is, DLL needs this string, to find User32.dll, if you want to see the complete projectplease download the daily Data Viewmov@hLocalUser32Module, EAX;The return value holds the address of the User32.dll module, giving the local variable @hRemoteUser32Module, eax; it's supposed to traverse the modules that are injected into the process.
To get the address of user32.dll, but here I have the same system, so the DLL location is the same, if you put this injection program to another system will be traversed by itself, the traversal code will not write, and invoke the API, as if not written, you can comment below.mov ;2. Get the address of the MessageBox functioninvoke GetProcess, @hLocalUser32Module, offset g_szmsgboxsup eax, @hLocalUser32Module;function Address-module address = actual offsetmovEbx,hremoteuser32module;give the handle of the other process to ebxAddEbx,eax;Remote Module address + actual offset = Remote function actual offset positionThis is for EBX to transfer the calculations .LeaEax,msg_box;find out where the inject label is locatedmov[Eax],ebx; write another actual function address and call
For the last two, find the location of the label, write the actual function address and call
This is in our Inject_code, the new application of a label position,
And then the inside of the memory is written to make our actual address
But now we find that there's a new problem.
Although we have written to Msg_box, we still can't run it properly.
Why is the code we write in is really the address of the MSG function?
But we need to know that we don't know where the code is going right now.
Like Inject_code, we're going to call this Msg_box address.
You will find that when call Msg_box is still a global constant, that is, your API address relocation problem has been solved, and now the
Code relocation is not resolved
See Understanding:
Now we have calculated the address of the API, but the address has not been calculated, this time we will ask, we do not traverse the DLL module address, it can not be used to use it, yes, but the problem is not here, you take it is also memory, but as long as you are in inject_ When code inside call,
is not called it, but you in the local process call, to the remote memory to write the past, remote also call,call is an address, and this address does not exist, then it will be wrong.
Like what:
We're going to calculate the offset of the code and the location of our code call.
That is, inject_code and the offset of the code written below us.
That's a bit of a distance, but it's not good for you in the remote process, so there's a new way.
See Assembly code
Push EBP Push ebx Call $+5; Call downlink command TEXT: Pop EBP ; Address Relocation Sub EBP, offset TEXT
First save the stack environment, EBP, we will use the ebx below, also save,
What does call $+5 mean, that together is called command to occupy five bytes, the next command will be placed in the stack when called, that is, the text command location into the stack
and immediately below the pop ebp, this is more important, mainly for what, we mainly to get the location of the IP
Imagine that call will put the following address into the stack, and then out of the stack to get the current IP code address.
Right
And then we wrote the
Sub Ebp,offset text, this is for what, we think about, in our this process, offset TEXT will be translated into a constant
When we have the ebp minus the text position, we get an offset from the EBP and the code position, looking at the figure
Think about it, another process minus our local offsets, get an offset, is not the equivalent of another process to get its own code position, and then we use the offset position of the EBP + function to derive the function address equivalent to the opposite program minus our address plus the offset of the function position
It's the same thing. Calling function addresses
Do not understand the picture, here more around, but it is important:
2000-1000 = 1000 This 1000 is the address relocation that is where the code is located, and then the offset of the function = where the actual code is executed
That's what remote threads do, too.
Already late at night, based on the relationship between the time, we first understand the concept, tomorrow, the day to re-edit the update
Classroom Code Connection: Link: http://pan.baidu.com/s/1bprSUcf Password: RSAG
32-bit Assembly IV, dry goods sharing, implementation of assembly injection, and number of fast-locating call APIs (OD view)