In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >
Share
Shulou(Shulou.com)05/31 Report--
This article mainly introduces what shellcode means. It is very detailed and has certain reference value. Friends who are interested must finish reading it.
First, the introduction of shellcode programming pre-knowledge points what is shellcode?
The essence of shellcode is a piece of assembly code that can run on its own. It doesn't have any file structure, it doesn't rely on any compilation environment, and it can't double-click to run like exe. Specific shellcode introduction to everyone can be their own Baidu, I will not be verbose here.
Why write your own shellcode?
Because there has been a lot of penetration in the past six months, and the shellcode used is also generated by CS or MSF, but the shellcode automatically generated by the tool is dead after all, and there is no way to expand the function by yourself, for example, you know a new loophole, but the loophole can only pop up a calculator if you want to use poc. If you want to achieve your desired function, you must write your own shellcode, so it is particularly important to master Shellcode writing technology. And shellcode is also an essential role in buffer overflows and worms.
Problems encountered in shellcode Writing
If you want to write shellcode yourself, you must know the most important knowledge points in shellcode writing. I will list a few points that need to be solved in the form of a problem:
1.Shellcode is also a program, which requires a variety of data (such as global strings, etc.) if it is to work properly, but we all know that global variable access is at a fixed address (hard-coded, that is, written to death, cannot be changed), and our shellcode may be arranged to run anywhere in any program. How can we ensure that shellcode can access the required data accurately in this case?
2.Shellcode also runs in the operating system, so it is necessary to call some system API. How can we get the addresses of these API?
3. What if Shellcode runs a program that doesn't import the API we need and we have to use it?
Because of the length of the answer to these questions, you can find answers from the three articles "introduction to Windows platform shellcode Development one, two, and three" translated by FB senior author Rabbit_Run. Basically, the pre-knowledge that shellcode needs to know is involved, and you can take questions to find answers.
2. Shellcode programming framework introduces the shellcode programming framework:
After knowing this pre-knowledge, it is still more troublesome and difficult for us to write shellcode by hand, just like writing native js code is not as convenient and fast as using js frameworks such as jquery. So we need to build a handy shellcode programming framework for us to develop our own functional shellcode in the future. Now there are many such shellcode programming frameworks on the Internet, such as the open source one of TK, the 2 models written by OneBugMan teacher, and so on. When I was studying at school, I wrote a shellcode programming framework by myself, but I couldn't find it, and I forgot a lot about my previous knowledge during this period of time, so I refer to OneBugMan teacher's curriculum (if you are interested, you can support the open class given by the teacher. I wrote a shellcode framework to practice it.
Introduction of frame structure
Fig. 1 frame structure diagram
This project is created as an empty win32 project, which uses VS2015 to compile relase/x86. Make the following settings before compilation:
1. Turn off SDL check when creating a project
two。 Attribute-> CumberCutters-> Code Generation-> Runtime-> Multithreading (/ MT) set to MTD if it is debug
3. Properties-> General-> platform toolsets-> set to Visual Studio 2015-Windows XP (v140_xp). If not, you can install the corresponding xp-compatible components on it.
4. Attribute-> CumberCraft checking-> Code Generation-> disable security check GS
5. Close generate manifest properties-> linker-> manifest file-> generate manifest Select No
Here's what each file does:
1. Api.hmuri-> shellcode uses function pointers to system functions, and a structure contains these function pointers.
2. Header file and function declaration of custom function.
3.0.entry.cppmuri-> framework entry to create the final generated shellcode file.
4.a.start.cppmuri-> marks the start position of shellcode, which is used for pre-operation before shellcode writing and initialization of functions used.
5.b.work.CPP shellcode-> execution, implementation of specific functions
6.z.end.CPPMI-> Mark the shellcode end position
The reason why the form of file naming is named in this way is because the files in the project are named in order to compile and generate exe in order to compile and generate exe according to the following figure. In this way, the order of the functions in the generated exe code snippet is also arranged in the order of the functions in the following figure file. In this way, we can easily calculate the size of Shellcode (ShellcodeEnd in z.end minus a.start. The ShellcodeStart in is the size of the shellcode), thus writing the shellcode to the final generated file.
Fig. 2 compilation sequence diagram
Explain the code in detail
The main attention in 0.entry.cpp is to modify the name of the entry point of the function must be consistent with the name of the function you wrote, otherwise you can't find the entry point, because we modified the entry point so some C-form functions can not be used directly, it should be changed to the form of dynamic calls, and we write the calculation of shellcode size.
Figure 3 0.entry.cpp code
In a.start.cpp, we mainly realize the most important preparations for writing shellcode: dynamically obtaining the matrix of kernel32.dll and using the knowledge of PE file format to obtain the address of GetProcAddress function, and further obtaining the address of LoadLibrary. With these pre-steps, we can obtain the address of other arbitrary API, and then realize the various functions of our shellcode.
Figure 4 getting the kernel32.dll base address
The following is the address of the GetProcAddress function. The reason why the GetProcAddress string should be written as shown below is that if you write the string [] = "xxxxx" in this way, the string will be written to the rdata segment of the program and become an absolute address. Using an absolute address will cause the shellcode to execute incorrectly.
FARPROC getProcAddress (HMODULE hModuleBase) {FARPROC pRet = NULL; PIMAGE_DOS_HEADER lpDosHeader; PIMAGE_NT_HEADERS32 lpNtHeaders; PIMAGE_EXPORT_DIRECTORY lpExports; PWORD lpwOrd; PDWORD lpdwFunName; PDWORD lpdwFunAddr; DWORD dwLoop; lpDosHeader = (PIMAGE_DOS_HEADER) hModuleBase; lpNtHeaders = (PIMAGE_NT_HEADERS) ((DWORD) hModuleBase + lpDosHeader- > e_lfanew); if (! lpNtHeaders- > OptionalHeader.DataDirection [image _ DIRECTORY_ENTRY_EXPORT] .size) {return pRet } if (! lpNtHeaders- > OptionalHeader.DataDirection [image _ DIRECTORY_ENTRY_EXPORT] .VirtualAddress) {return pRet;} lpExports = (PIMAGE_EXPORT_DIRECTORY) ((DWORD) hModuleBase + (DWORD) lpNtHeaders- > OptionalHeader.DataDirection [image _ DIRECTORY_ENTRY_EXPORT] .VirtualAddress); if (! lpExports- > NumberOfNames) {return pRet;} lpdwFunName = (PDWORD) ((DWORD) hModuleBase + (DWORD) lpExports- > AddressOfNames) LpwOrd = (PWORD) ((DWORD) hModuleBase + (DWORD) lpExports- > AddressOfNameOrdinals); lpdwFunAddr = (PDWORD) ((DWORD) hModuleBase + (DWORD) lpExports- > AddressOfFunctions); for (dwLoop = 0; dwLoop NumberOfNames-1; dwLoop++) {char* pszFunction = (char*) (lpdwFunname [dwLoop] + (DWORD) hModuleBase) If (pszFunction [0] = ='G' & & pszFunction [1]) = ='e' & & pszFunction [2] = ='t'& & pszFunction [3] ='P' & & pszFunction [4] = ='r'& & pszFunction [5] = ='o' & & pszFunction [6] = ='c'& & pszFunction [ 7] ='A' & & pszFunction [8] = ='d' & & pszFunction [9] = ='d' & & pszFunction [10] = ='r' & & pszFunction [11] = ='e' & & pszFunction [12] = ='s'& & pszFunction [13] = ='s') {pRet = (FARPROC) ( LpdwFunAdr [lpwOrd [dwLoop]] + (DWORD) hModuleBase) In the initialization function section below break;}} return pRet;}, we need to know which dll the function we are using is in. For example, if we want to use the system () function to execute the command, we need to load msvCRT.dll first in the following figure, and then find the system function through the getprocaddress function. Don't forget that the command string used in the system function (for example, calling a calculator) should also be written like char szCalc [] = {'centering force. Figure 5 initialization function
When implementing the specific function, you only need to remember to declare the strings used in the function according to the following array. Here we write the function of the example to pop up a message box prompting hello, and then create an 1.txt document.
Figure 6 implementation of specific functions of b.work.cpp
Third, execute shellcode
After the framework code is written, our run will generate a sc.bin file in the project directory, in which we can open sc.bin using 010Editor to see the generated shellcode.
Figure 7 generated shellcode
Here are several ways to run shellcode: 1. (use 010Editor to copy shellcode directly) directly replace the binary of a program.
For example, we want dbgview.exe to run the shellcode we generated.
Step 1: we use lordPE to view the entry point of the dbgview.exe program.
Then use 010Editor to open dbgview.exe to find the entry point location, delete the shellcode size bytes we need to replace from the entry point location, and then replace it with our shellcode, save and run to execute our shellcode.
2. Write shellcode directly into code to generate exe program to run (source code A), or generate dll rewrite injector or use tools to inject into a process (source code B)
Source code A
# include # include # pragma comment (linker, "/ section:.data,RWE") unsigned char shellcode [] = "\ xfc\ xe8\ x89\ x00\ x00\ x60\ x89. Write shellcode here"; void main () {_ asm {mov eax, offset shellcode jmp eax}}
Source code B
/ / dllmain.cpp: defines the entry point for DLL applications. # include "stdafx.h" # include#include//data paragraph is readable and writable # pragma comment (linker, "/ section:.data,RWE") HANDLE My_hThread = NULL;//void (* ptrceshi) () = NULL;typedef void (_ _ stdcall * CODE) (); unsigned char shellcode [] = "X00\ x49\ xbe\ x77\ x69\ x6e\ x. Fill in shellcode "; DWORD WINAPI ceshi (LPVOID pParameter) {PVOID p = NULL; if ((p = VirtualAlloc (NULL, sizeof (shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)) = = NULL) {} if (! (memcpy (p, shellcode, sizeof (shellcode) {} CODE code = (CODE) p; code (); return 0 } BOOL APIENTRY DllMain (HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {switch (ul_reason_for_call) {case DLL_PROCESS_ATTACH: My_hThread =:: CreateThread (NULL, 0, & ceshi, 0,0,0) / / create a new thread case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break;} return TRUE;} for more information, please refer to my previous article, "steps in shellcode Kill-free practice". 3. Write your own loader
If we don't want to copy out the shellcode to run, we can run the sc.bin we generated directly, but we need to write a loader ourselves.
The code is as follows
# include#include#includeint main (int argc, char* argv []) {HANDLE hFile = CreateFileA (argv [1], GENERIC_READ, 0, NULL, OPEN_ALWAYS, 0, NULL); if (hFile = = INVALID_HANDLE_VALUE) {printf ("Open File errors% d\ n", GetLastError ()); return-1;} DWORD dwSize; dwSize = GetFileSize (hFile, NULL) LPVOID lpAddress = VirtualAlloc (NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (lpAddress = = NULL) {printf ("VirtualAlloc error:%d\ n", GetLastError ()); CloseHandle (hFile); return-1;} DWORD dwRead; ReadFile (hFile, lpAddress, dwSize, & dwRead, 0); _ _ asm {call lpAddress;} _ flushall (); system ("pause") Return 0;}
After writing the loader and compiling to generate exe, we just need to drag the sc.bin file to the generated exe to run our shellcode automatically, or use the command line > xxe sc.bin
4. Use the loader written by others
If you do not want to write their own loader can also use tools written by others, I used to look at the snow found that a gadget is also very useful, this gadget can convert shellcode into a string form can also be a string form of shellcode into bin file form and then load and run shellcode.
Original post link tool link
Let's use this tool to execute the sc.bin we generated, drag the sc.bin into the tool, and we can click to turn it into a string.
This is the same as what we see in 010Editor, which is equivalent to helping us to copy it automatically.
Because the sc.bin file we generated can be executed directly, there is no need to click to turn it into a Bin file, so we directly click on the execution shellcode, and the Messagebox window pops up. After we click OK, we create the 1.txt document.
At this point, we can follow the example of the framework and write our own functional shellcode.
The above is all the contents of this article "what does shellcode mean?" Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.