Although the last thing turned out to be depressing, there were still some gains in the intermediate process,
When compiling shellcode, it is very important to find the location of the function to be used in the memory. There are many templates written on the Internet, and the method is as follows:
It is found through peb and Seh. The template found uses peb.
The main purpose is to find the location of kernel. dll in the memory, and then find the location of getprocaddress (). With these two, you can
There is loadlibrary (), and other function address problems are solved.
FS: 0 indicates the location of Teb, and Teb offset 0x30 indicates peb.
Typedef struct _ peb {
Boolean inheritedaddressspace;
Boolean readimagefileexecoptions;
Boolean beingdebugged;
Boolean spare;
Handle mutant;
Pvoid imagebaseaddress;
Ppeb_ldr_data loaderdata;
Prtl_user_process_parameters processparameters;
Pvoid subsystemdata;
Pvoid processheap;
Pvoid fastpeblock;
Ppeblockroutine fastpeblockroutine;
Ppeblockroutine fastpebunlockroutine;
Ulong environmentupdatecount;
Pvoid * kernelcallbacktable;
Pvoid eventlogsection;
Pvoid Eventlog;
Ppeb_free_block freelist;
Ulong tlsexpansioncounter;
Pvoid tlsbitmap;
Ulong tlsbitmapbits [0x2];
Pvoid readonlysharedmemorybase;
Pvoid readonlysharedmemoryheap;
Pvoid * readonlystaticserverdata;
Pvoid ansicodepagedata;
Pvoid oemcodepagedata;
Pvoid unicodecasetabledata;
Ulong numberofprocessors;
Ulong ntglobalflag;
Byte spare2 [0x4];
Large_integer criticalsectiontimeout;
Ulong heapsegmentreserve;
Ulong heapsegmentcommit;
Ulong heapdecommittotalfreethreshold;
Ulong heapdecommitfreeblockthreshold;
Ulong numberofheaps;
Ulong maximumnumberofheaps;
Pvoid ** processheaps;
Pvoid gdisharedhandletable;
Pvoid processstarterhelper;
Pvoid gdidcattributelist;
Pvoid loaderlock;
Ulong osmajorversion;
Ulong osminorversion;
Ulong osbuildnumber;
Ulong osplatformid;
Ulong imagesubsystem;
Ulong imagesubsystemmajorversion;
Ulong imagesubsystemminorversion;
Ulong gdihandlebuffer [0x22];
Ulong postprocessinitroutine;
Ulong tlsexpansionbitmap;
Byte tlsexpansionbitmapbits [0x80];
Ulong sessionid;
} Peb, * ppeb;
The peb offset 0x0c is ppeb_ldr_data loaderdata;
Typedef struct _ peb_ldr_data {
Ulong length;
Boolean initialized;
Pvoid sshandle;
List_entry inloadordermodulelist;
List_entry inmemoryordermodulelist;
List_entry ininitializationordermodulelist;
} Peb_ldr_data, * ppeb_ldr_data;
There are three linked lists, each of which is structured.
Typedef struct _ ldr_module {
List_entry inloadordermodulelist;
List_entry inmemoryordermodulelist;
List_entry ininitializationordermodulelist;
Pvoid baseaddress;
Pvoid entrypoint;
Ulong sizeofimage;
Unicode_string fulldllname;
Unicode_string basedllname;
Ulong flags;
Short loadcount;
Short tlsindex;
List_entry hashtableentry;
Ulong timedatestamp;
} Ldr_module, * pldr_module;
Use list_entry to concatenate the modules used by each process. Each module is an image of an executable file or DLL in the memory.
A connection can take all the DLL used by the process, while shellcode requires kernel32.dll, which is always located in the ininitializa linked list.
The first element of tionordermodulelist
MoV eax, FS: 0x30 // peb
MoV eax, [eax + 0x0c] // process_module_info
MoV ESI, [eax + 0x1c] // inininitorder. flink
Lodsd
// Obtain the ininitializationordermodulelist address of the ldr_module structure where kernel. dll is located.
MoV eax, [eax + 8] // A list_entry8 byte
In the current eax, it is the start position of the kernel. dll in the memory image, that is, its handle value.
After finding kernel. dll, the following part is related to the PE file format,
MoV EBX, eax // get the starting address of kernel32.dll
MoV ESI, dword ptr [EBX + 0x3c] // u get PE Header in e_lfanew
MoV ESI, dword ptr [ESI + EBX + 0x78] // U export directory RVA
Add ESI, EBX
MoV EDI, dword ptr [ESI + 0x20] // U struct _ image_export_directory
// Addressofnames; // RVA from base of Image
Add EDI, EBX
MoV ECx, dword ptr [ESI + 0x14] // U addressoffunctions; // RVA from base of Image
Xor ebp, EBP
Push ESI
Search_getprocaddress:
Push EDI
Push ECx
MoV EDI, dword ptr [EDI]
Add EDI, EBX // Save the start address of the output function table to EDI
MoV ESI, EDX // The starting address of the instruction table stored in ESI
// Mov ECx, 0eh // The length of the getprocaddress function is 0eh
Push 0xe
Pop ECx
Repe CMPs byte PTR [esi], byte PTR [EDI]
Je search_getprocaddress_ OK
Pop ECx
Pop EDI
Add EDI, 4
INC EBP
Loop search_getprocaddress
Search_getprocaddress_ OK:
Pop ECx
Pop EDI
Pop ESI
MoV ECx, EBP
MoV eax, dword ptr [ESI + 24 h] // U addressofnameordinals; // RVA from base of Image
Add eax, EBX
SHL ECx, 1
Add eax, ECx
XOR ECx, ECx
MoV CX, word PTR [eax]
MoV eax, dword ptr [ESI + 1ch] // addressoffunctions; // RVA from base of Image
Add eax, EBX
SHL ECx, 2
Add eax, ECx
MoV eax, dword ptr [eax]
Add eax, EBX
In the PE file, it is initially the image_dos_header Structure
Typedef struct _ image_dos_header {// dos. EXE Header
Word e_magic; // magic number
Word e_cblp; // bytes on last page of File
Word e_cp; // pages in file
Word e_crlc; // relocations
Word e_cparhdr; // size of header in paragraphs
Word e_minalloc; // minimum extra paragraphs needed
Word e_maxalloc; // maximum extra paragraphs needed
Word e_ss; // initial (relative) SS value
Word e_sp; // initial sp value
Word e_csum; // checksum
Word e_ip; // initial IP value
Word e_cs; // initial (relative) Cs value
Word e_lfarlc; // file address of relocation table
Word e_ovno; // overlay number
Word e_res [4]; // Reserved Words
Word e_oemid; // OEM identifier (for e_oeminfo)
Word e_oeminfo; // OEM information; e_oemid specific
Word e_res2 [10]; // Reserved Words
Long e_lfanew; // file address of New EXE Header
} Image_dos_header, * pimage_dos_header;
MoV ESI, dword ptr [EBX + 0x3c] is to get long e_lfanew, ESI points to the PE Header, because it is relative to the file
So ESI + EBX is the position of the PE Header of kernell. dll in the memory. Add 0x78 to point to datadirectory,
Typedef struct _ image_nt_headers {
DWORD signature;
Image_file_header fileheader;
Image_optional_header32 optionalheader;
} Image_nt_headers32, * pimage_nt_headers32;
Typedef struct _ image_optional_header {
//
// Standard fields.
//
Word magic;
Byte majorlinkerversion;
Byte minorlinkerversion;
DWORD sizeofcode;
DWORD sizeofinitializeddata;
DWORD sizeofuninitializeddata;
DWORD addressofentrypoint;
DWORD baseofcode;
DWORD baseofdata;
//
// Nt additional fields.
//
DWORD imagebase;
DWORD sectionalignment;
DWORD filealignment;
Word majoroperatingsystemversion;
Word minoroperatingsystemversion;
Word majorimageversion;
Word minorimageversion;
Word majorsubsystemversion;
Word minorsubsystemversion;
DWORD win32versionvalue;
DWORD sizeofimage;
DWORD sizeofheaders;
DWORD checksum;
Word subsystem;
Word dllcharacteristics;
DWORD sizeofstackreserve;
DWORD sizeofstackcommit;
DWORD sizeofheapreserve;
DWORD sizeofheapcommit;
DWORD loaderflags;
DWORD numberofrvaandsizes;
Image_data_directory datadirectory [image_numberof_directory_entries];
} Image_optional_header32, * pimage_optional_header32;
The first of datadirectory is exportdirectory. Adding EBX is the location in the memory. Each directory starts with a structure.
Typedef struct _ image_export_directory {
DWORD characteristics;
DWORD timedatestamp;
Word majorversion;
Word minorversion;
DWORD name;
DWORD base;
DWORD numberoffunctions;
DWORD numberofnames;
DWORD addressoffunctions; // RVA from base of Image
DWORD addressofnames; // RVA from base of Image
DWORD addressofnameordinals; // RVA from base of Image
} Image_export_directory, * pimage_export_directory;
Addressofnames and the address behind it are a pointer array. Each element points to the RVA of a function name string.
Sample
(Char *) (* (int *) ADDR) + baseaddress)
Addressofnameordinals corresponds to addressofnames one by one, which is the serial number of the function in addressoffunctions
When calling this function, if the function name is used for searching, find the corresponding item in addressofnames to obtain the pointer
Position in the array, which is used to extract the response element in addressofnameordinals,
MoV ECx, EBP
MoV eax, dword ptr [ESI + 24 h] // U addressofnameordinals;
Add eax, EBX
SHL ECx, 1
Add eax, ECx
That is, the size of each element in the addressofnameordinals array is word, so SHL ECx, 1
XOR ECx, ECx
MoV CX, word PTR [eax]
The CX is used to index addressoffunctions;. The content of each element in addressoffunctions is the RVA of the function.
The base address of kernell. dll is located in the memory.
Add eax, EBX
SHL ECx, 1
Add eax, ECx
XOR ECx, ECx
MoV CX, word PTR [eax]
MoV eax, dword ptr [ESI + 1ch] // addressoffunctions; // RVA from base of Image
Add eax, EBX
SHL ECx, 2
Add eax, ECx
MoV eax, dword ptr [eax]
Add eax, EBX
After obtaining the address of getprocaddress, you can use it to obtain the address of loadlibrary, because loadlibrary is also exported from kernel. dll.
Function, and then there are these two functions. Nothing else worries about them.