Next we will take the release version as an example to illustrate the anatomy.
The key code for the EXE disassembly is as follows:
Function showcomputername:
00401030: 8B 4C 24 04 mov ECx, dword ptr [esp + 4]
00401034: 83 EC 0C sub ESP, 0ch
00401037: 8d 44 24 00 Lea eax, [esp]
0040103b: 50 push eax
0040103c: 51 push ECx
0040103d: E8 be FF call 00401000
00401042: 83 C4 14 add ESP, 14 h
00401045: C3 RET
Main function:
00401080: 68 30 50 40 00 push 405030 H
00401085: E8 A6 FF call 00401030 0040108a: 83 C4 04 add ESP, 4
We know that function calls use the stack method. How does the CPU work?
In the Windows XP/2000 operating system, we can see through a large number of assembly code that the parameter passing of function calls is carried out using stacks.
Why?
The reason is that the personal computer we use generally uses the x86 series CPU, because there are very few general-purpose registers available, we can only use the stack. The PowerPC series CPU used by the author has 32 General registers, so the function call parameters use registers R3, R4 ...... . It is said that the use of PowerPC should be based on the register transfer method, but the author does not have an apple machine, you can look at it yourself.
Next I will return to the question. How can I run this code?
Assuming that the code runs at 00401080, the ESP pointer is 00130000
How will the stack develop?
| ............ | Low address
+ ------------------------------ +
|
+ ------------------------------ + High address ESP 00130000
After 405030h is pushed, The 405030h is pushed to the stack, and the ESP pointer is moved up.
| ............ |
+ ------------------------------ + ESP 0012 fffc
| 00405030 H |
+ ------------------------------ +
After call 00401030 is completed, the showcomputername function is called.
After the function is called, The EIP address 0040108a of the main function is returned to be pushed to the stack, and the ESP pointer is moved up. This stack pressure value is the purpose of overflow attacks.
| ............ |
+ ------------------------------ + ESP 0012fff8
| 004020.ah |
+ ------------------------------ +
| 00405030 H |
+ ------------------------------ +
Next we will go to the overflow function section. We can know that ESP is 0012fff8, so mov ECx, dword ptr [esp + 4] is to extract the first address of the array of the Pressure stack and place it in the register ECx.
Next, sub ESP, 0ch, is the space reserved for the local variable puccomputername, exactly 12 bytes. ESP moves 12 bytes up, that is, the first address of puccomputername.
| ............ |
+ ------------------------------ + ESP 0012 ffec
| Puccomputername |
| Space |
|
+ ------------------------------ +
| 004020.ah |
+ ------------------------------ +
| 00405030 H |
+ ------------------------------ +
Then Lea eax and [esp] assign the ESP value to eax. Now eax points to the first address of puccomputername, and exc points to the first address of global variable g_aucname.
0040103b: 50 push eax
0040103c: 51 push ECx
Eax and ECx are used when the function getname is called and the stack space diagram is changed:
| ............ |
+ ------------------------------ + ESP 0012ffe4
| 00405030 H |
+ ------------------------------ +
| 0012 ffech |
+ ------------------------------ +
| Puccomputername |
| Space |
|
+ ------------------------------ +
| 004020.ah |
+ ------------------------------ +
| 00405030 H |
+ ------------------------------ +
Next, call the function getname to return the EIP pointer 00401042 of the showcomputername function to the stack. The ESP is moved up again, and the stack space diagram is changed:
| ............ |
+ ------------------------------ + ESP 0012ffe0
| 00401042 H |
+ ------------------------------ +
| 00405030 H |
+ ------------------------------ +
| 0012 ffech |
+ ------------------------------ +
| Puccomputername |
| Space |
|
+ ------------------------------ +
| 004020.ah |
+ ------------------------------ +
| 00405030 H |
+ ------------------------------ +
Next, the getname function copies all the content of g_aucname to the address where the local variable puccomputername is located. Because the local variable uses the stack space, in this way, the EIP returned by the main function is ruthlessly rewritten, deceiving the CPU and achieving the goal.
The stack space status of the showcomputername function is not returned after the copy is completed.
| ............ |
+ ------------------------------ + ESP 0012ffe0
| 00401042 H |
+ ------------------------------ +
| 00405030 H |
+ ------------------------------ +
| 0012 ffech |
+ ------------------------------ +
| 'H', 'E', 'l', 'L' |
| 'O', 'w', 'O', 'R' |
| 'L', 'D ','! ','/0' |
+ ------------------------------ +
| 00401072 H |
+ ------------------------------ +
| 0x6a, 0x00,0x68,0x30, |
+ ------------------------------ +
| 0x50, 0x40, 0x0x68, |
+ ------------------------------ +
| 0x30, 0x50, 0x40, 0x00, |
+ ------------------------------ +
| 0x6a, 0x00, 0xff, 0x15, |
+ ------------------------------ +
| 0x90, 0x40, 0x40, 0x00, |
+ ------------------------------ +
| 0x6a, 0x00, 0xff, 0x15, |
+ ------------------------------ +
| 0x48, 0x40, 0x40, 0x00, |
+ ------------------------------ +
The retained EIP pointer and ESP pointer of the getname call relation are not damaged. Therefore, RET can return normally.
The EIP is set to 00401042 h, and the ESP is moved down to 0012ffe4.
Next we will execute the command where 00401042 is located, that is, add ESP, 14 h. Why is it 14h? Is it because we didn't push two function parameters? "Pop-up" is also required here. This non-pop-up is the compiler optimization result, and the ESP is the fastest and most direct. 14 h = 0ch + 08 h
In this way, the ESP pointer is moved down to 0012fff8. At this time, you can see what the returned address is? The address where the jmp esp command is located. After RET is executed, the EIP is set to 00401072 h, and the ESP is moved down to 0012 fffc.
The EIP command to be executed is jmp esp, And the ESP address is our overflow attack command. What has happened below I believe everyone understands, that is, the part of the program that we attack our own overflow vulnerability is activated.
It's too late to write it here.
For more information about how to write this attack program, see the next article. Pai_^