??????? 在內存中運行可執行程序,好處是可以給程序加殼,加密源程序,靜態反匯編無法獲得PE輸入節,但是因為運行后仍然是獨立的進程,所以沒辦法防止遠程線程注入,掛接API鉤子。
??
typedef?IMAGE_SECTION_HEADER?(
*
PIMAGE_SECTION_HEADERS)[
1
];???
??
//
?計算對齊后的大小???
unsigned?
long
?GetAlignedSize(unsigned?
long
?Origin,?unsigned?
long
?Alignment)???

{???
????
return
?(Origin?
+
?Alignment?
-
?
1
)?
/
?Alignment?
*
?Alignment;???
}
???
??
//
?計算加載pe并對齊需要占用多少內存???
//
?未直接使用OptionalHeader.SizeOfImage作為結果是因為據說有的編譯器生成的exe這個值會填0???
unsigned?
long
?CalcTotalImageSize(PIMAGE_DOS_HEADER?MzH???
?????????????????????????????????,?unsigned?
long
?FileLen???
?????????????????????????????????,?PIMAGE_NT_HEADERS?peH???
?????????????????????????????????,?PIMAGE_SECTION_HEADERS?peSecH)???

{???
????unsigned?
long
?res;???
????
//
?計算pe頭的大小???
????res?
=
?GetAlignedSize(?peH
->
OptionalHeader.SizeOfHeaders?,?peH
->
OptionalHeader.SectionAlignment);???
??
????
//
?計算所有節的大小???
????
for
(?
int
?i?
=
?
0
;?i?
<
?peH
->
FileHeader.NumberOfSections;?
++
i)???

????
{???
????????
//
?超出文件范圍???
????????
if
(peSecH[i]
->
PointerToRawData?
+
?peSecH[i]
->
SizeOfRawData?
>
?FileLen)??

????????
{
????????????
return
?
0
;???
????????}
????????
else
?
if
(peSecH[i]
->
VirtualAddress)
//
計算對齊后某節的大小???
????????
{???
????????????
if
(peSecH[i]
->
Misc.VirtualSize)???

????????????
{???
????????????????res?
=
?GetAlignedSize(?peSecH[i]
->
VirtualAddress?
+
?peSecH[i]
->
Misc.VirtualSize???
????????????????????,?peH
->
OptionalHeader.SectionAlignment);???
????????????}
???
????????????
else
??

????????????
{???
????????????????res?
=
?GetAlignedSize(?peSecH[i]
->
VirtualAddress?
+
?peSecH[i]
->
SizeOfRawData???
????????????????????,?peH
->
OptionalHeader.SectionAlignment);???
????????????}
???
????????}
???
????????
else
?
if
(?peSecH[i]
->
Misc.VirtualSize?
<
?peSecH[i]
->
SizeOfRawData?)???

????????
{???
????????????res?
+=
?GetAlignedSize(?peSecH[i]
->
SizeOfRawData???
????????????????,?peH
->
OptionalHeader.SectionAlignment);???
????????}
???
????????
else
??

????????
{???
????????????res?
+=
?GetAlignedSize(?peSecH[i]
->
Misc.VirtualSize???
????????????????,?peH
->
OptionalHeader.SectionAlignment);???
????????}
//
?if_else???
????}
//
?for???
???????
????
return
?res;???
}
???
??
??
??
??
//
?加載pe到內存并對齊所有節???
BOOL?AlignPEToMem(?
void
?
*
Buf???
??????????????????,?
long
?Len???
??????????????????,?PIMAGE_NT_HEADERS?
&
peH???
??????????????????,?PIMAGE_SECTION_HEADERS?
&
peSecH???
??????????????????,?
void
?
*&
Mem???
??????????????????,?unsigned?
long
?
&
ImageSize)???

{???
????PIMAGE_DOS_HEADER?SrcMz;
//
?DOS頭???
????PIMAGE_NT_HEADERS?SrcPeH;
//
?PE頭???
????PIMAGE_SECTION_HEADERS?SrcPeSecH;
//
?節表???
???????
????SrcMz?
=
?(PIMAGE_DOS_HEADER)Buf;???
??
????
if
(?Len?
<
?
sizeof
(IMAGE_DOS_HEADER)?)????
????????
return
?FALSE;???
???????
????
if
(?SrcMz
->
e_magic?
!=
?IMAGE_DOS_SIGNATURE?)???
????????
return
?FALSE;???
???????
????
if
(?Len?
<
?SrcMz
->
e_lfanew?
+
?(
long
)
sizeof
(IMAGE_NT_HEADERS)?)???
????????
return
?FALSE;???
??
????SrcPeH?
=
?(PIMAGE_NT_HEADERS)((
int
)SrcMz?
+
?SrcMz
->
e_lfanew);???
????
if
(?SrcPeH
->
Signature?
!=
?IMAGE_NT_SIGNATURE?)???
????????
return
?FALSE;???
??
????
if
(?(SrcPeH
->
FileHeader.Characteristics?
&
?IMAGE_FILE_DLL)?
||
???
????????(SrcPeH
->
FileHeader.Characteristics?
&
?IMAGE_FILE_EXECUTABLE_IMAGE?
==
?
0
)?
||
???
????????(SrcPeH
->
FileHeader.SizeOfOptionalHeader?
!=
?
sizeof
(IMAGE_OPTIONAL_HEADER))?)???

????
{???
????????
return
?FALSE;???
????}
???
??
??
????SrcPeSecH?
=
?(PIMAGE_SECTION_HEADERS)((
int
)SrcPeH?
+
?
sizeof
(IMAGE_NT_HEADERS));???
????ImageSize?
=
?CalcTotalImageSize(?SrcMz,?Len,?SrcPeH,?SrcPeSecH);???
??
????
if
(?ImageSize?
==
?
0
?)???
????????
return
?FALSE;???
???????
????Mem?
=
?VirtualAlloc(?NULL,?ImageSize,?MEM_COMMIT,?PAGE_EXECUTE_READWRITE);?
//
?分配內存???
????
if
(?Mem?
!=
?NULL?)???

????
{???
????????
//
?計算需要復制的PE頭字節數???
????????unsigned?
long
?l?
=
?SrcPeH
->
OptionalHeader.SizeOfHeaders;???
????????
for
(?
int
?i?
=
?
0
;?i?
<
?SrcPeH
->
FileHeader.NumberOfSections;?
++
i)???

????????
{???
????????????
if
(?(SrcPeSecH[i]
->
PointerToRawData)?
&&
???
????????????????(SrcPeSecH[i]
->
PointerToRawData?
<
?l)?)???

????????????
{???
????????????????l?
=
?SrcPeSecH[i]
->
PointerToRawData;???
????????????}
???
????????}
???
????????memmove(?Mem,?SrcMz,?l);???
????????peH?
=
?(PIMAGE_NT_HEADERS)((
int
)Mem?
+
?((PIMAGE_DOS_HEADER)Mem)
->
e_lfanew);???
????????peSecH?
=
?(PIMAGE_SECTION_HEADERS)((
int
)peH?
+
?
sizeof
(IMAGE_NT_HEADERS));???
??
????????
void
?
*
Pt?
=
?(
void
?
*
)((unsigned?
long
)Mem????
????????????
+
?GetAlignedSize(?peH
->
OptionalHeader.SizeOfHeaders???
????????????,?peH
->
OptionalHeader.SectionAlignment)???
????????????);???
??
????????
for
(?i?
=
?
0
;?i?
<
?peH
->
FileHeader.NumberOfSections;?
++
i)???

????????
{???
????????????
//
?定位該節在內存中的位置???
????????????
if
(peSecH[i]
->
VirtualAddress)???
????????????????Pt?
=
?(
void
?
*
)((unsigned?
long
)Mem?
+
?peSecH[i]
->
VirtualAddress);???
??
????????????
if
(peSecH[i]
->
SizeOfRawData)???

????????????
{???
????????????????
//
?復制數據到內存???
????????????????memmove(Pt,?(
const
?
void
?
*
)((unsigned?
long
)(SrcMz)?
+
?peSecH[i]
->
PointerToRawData),?peSecH[i]
->
SizeOfRawData);???
????????????????
if
(peSecH[i]
->
Misc.VirtualSize?
<
?peSecH[i]
->
SizeOfRawData)???
????????????????????Pt?
=
?(
void
?
*
)((unsigned?
long
)Pt?
+
?GetAlignedSize(peSecH[i]
->
SizeOfRawData,?peH
->
OptionalHeader.SectionAlignment));???
????????????????
else
?
//
?pt?定位到下一節開始位置???
????????????????????Pt?
=
?(
void
?
*
)((unsigned?
long
)Pt?
+
?GetAlignedSize(peSecH[i]
->
Misc.VirtualSize,?peH
->
OptionalHeader.SectionAlignment));???
????????????}
???
????????????
else
??

????????????
{???
????????????????Pt?
=
?(
void
?
*
)((unsigned?
long
)Pt?
+
?GetAlignedSize(peSecH[i]
->
Misc.VirtualSize,?peH
->
OptionalHeader.SectionAlignment));???
????????????}
???
????????}
???
????}
???
????
return
?TRUE;???
}
???
??
??
??
typedef?
void
?
*
(__stdcall?
*
pfVirtualAllocEx)(unsigned?
long
,?
void
?
*
,?unsigned?
long
,?unsigned?
long
,?unsigned?
long
);???
pfVirtualAllocEx?MyVirtualAllocEx?
=
?NULL;???
??
BOOL?IsNT()???

{???
????
return
?MyVirtualAllocEx
!=
NULL;???
}
???
??
//
?生成外殼程序命令行???
char
?
*
PrepareShellExe(
char
?
*
CmdParam,?unsigned?
long
?BaseAddr,?unsigned?
long
?ImageSize)???

{???
????
if
(IsNT())???

????
{???
????????
char
?
*
Buf?
=
?
new
?
char
[
256
];???
????????memset(Buf,?
0
,?
256
);???
????????GetModuleFileName(
0
,?Buf,?
256
);???
????????strcat(Buf,?CmdParam);???
????????
return
?Buf;?
//
?請記得釋放內存;-)???
????}
???
????
else
??

????
{???
????????
//
?Win98下的處理請參考原文;-)???
????????
//
?
http://community.csdn.net/Expert/topic/4416/4416252.xml?temp=8.709133E-03
???
????????
return
?NULL;???
????}
???
}
???
??
//
?是否包含可重定向列表???
BOOL?HasRelocationTable(PIMAGE_NT_HEADERS?peH)???

{???
????
return
?(peH
->
OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)???
????????
&&
?(peH
->
OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);???
}
???
??
??
??
??
#pragma?pack(push,?
1
)???

typedef?
struct
{???
????unsigned?
long
?VirtualAddress;???
????unsigned?
long
?SizeOfBlock;???
}
?
*
PImageBaseRelocation;???
#pragma?pack(pop)???
??
//
?重定向PE用到的地址???
void
?DoRelocation(PIMAGE_NT_HEADERS?peH,?
void
?
*
OldBase,?
void
?
*
NewBase)???

{???
????unsigned?
long
?Delta?
=
?(unsigned?
long
)NewBase?
-
?peH
->
OptionalHeader.ImageBase;???
????PImageBaseRelocation?p?
=
?(PImageBaseRelocation)((unsigned?
long
)OldBase????
????????
+
?peH
->
OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);???
????
while
(p
->
VirtualAddress?
+
?p
->
SizeOfBlock)???

????
{???
????????unsigned?
short
?
*
pw?
=
?(unsigned?
short
?
*
)((
int
)p?
+
?
sizeof
(
*
p));???
????????
for
(unsigned?
int
?i
=
1
;?i?
<=
?(p
->
SizeOfBlock?
-
?
sizeof
(
*
p))?
/
?
2
;?
++
i)???

????????
{???

????????????
if
((
*
pw)?
&
?
0xF000
?
==
?
0x3000
)
{???
????????????????unsigned?
long
?
*
t?
=
?(unsigned?
long
?
*
)((unsigned?
long
)(OldBase)?
+
?p
->
VirtualAddress?
+
?((
*
pw)?
&
?
0x0FFF
));???
????????????????
*
t?
+=
?Delta;???
????????????}
???
????????????
++
pw;???
????????}
???
????????p?
=
?(PImageBaseRelocation)pw;???
????}
???
}
???
??
//
?卸載原外殼占用內存???
BOOL?UnloadShell(HANDLE?ProcHnd,?unsigned?
long
?BaseAddr)???

{???
????typedef?unsigned?
long
?(__stdcall?
*
pfZwUnmapViewOfSection)(unsigned?
long
,?unsigned?
long
);???
????pfZwUnmapViewOfSection?ZwUnmapViewOfSection?
=
?NULL;???
????BOOL?res?
=
?FALSE;???
????HMODULE?m?
=
?LoadLibrary(
"
ntdll.dll
"
);???

????
if
(m)
{???
????????ZwUnmapViewOfSection?
=
?(pfZwUnmapViewOfSection)GetProcAddress(m,?
"
ZwUnmapViewOfSection
"
);???
????????
if
(ZwUnmapViewOfSection)???
????????????res?
=
?(ZwUnmapViewOfSection((unsigned?
long
)ProcHnd,?BaseAddr)?
==
?
0
);???
????????FreeLibrary(m);???
????}
???
????
return
?res;???
}
???
??
//
?創建外殼進程并獲取其基址、大小和當前運行狀態???
BOOL?CreateChild(
char
?
*
Cmd,?CONTEXT?
&
Ctx,?HANDLE?
&
ProcHnd,?HANDLE?
&
ThrdHnd,????
?????????????????unsigned?
long
?
&
ProcId,?unsigned?
long
?
&
BaseAddr,?unsigned?
long
?
&
ImageSize)???

{???
????STARTUPINFOA?si;???
????PROCESS_INFORMATION?pi;???
????unsigned?
long
?old;???
????MEMORY_BASIC_INFORMATION?MemInfo;???
????memset(
&
si,?
0
,?
sizeof
(si));???
????memset(
&
pi,?
0
,?
sizeof
(pi));???
????si.cb?
=
?
sizeof
(si);???
???????
????BOOL?res?
=
?CreateProcess(NULL,?Cmd,?NULL,?NULL,?FALSE,?CREATE_SUSPENDED,?NULL,?NULL,?
&
si,?
&
pi);?
//
?以掛起方式運行進程;???
????
if
(res)
{???
????????ProcHnd?
=
?pi.hProcess;???
????????ThrdHnd?
=
?pi.hThread;???
????????ProcId?
=
?pi.dwProcessId;???
????????
//
?獲取外殼進程運行狀態,[ctx.Ebx+8]內存處存的是外殼進程的加載基址,ctx.Eax存放有外殼進程的入口地址???
????????Ctx.ContextFlags?
=
?CONTEXT_FULL;???
????????GetThreadContext(ThrdHnd,?
&
Ctx);???
????????ReadProcessMemory(ProcHnd,?(
void
?
*
)(Ctx.Ebx
+
8
),?
&
BaseAddr,?
sizeof
(unsigned?
long
),?
&
old);?
//
?讀取加載基址???
????????
void
?
*
p?
=
?(
void
?
*
)BaseAddr;???
????????
//
?計算外殼進程占有的內存???
????????
while
(VirtualQueryEx(ProcHnd,?p,?
&
MemInfo,?
sizeof
(MemInfo)))???

????????
{???
????????????
if
(MemInfo.State?
=
?MEM_FREE)?
break
;???
????????????p?
=
?(
void
?
*
)((unsigned?
long
)p?
+
?MemInfo.RegionSize);???
????????}
???
????????ImageSize?
=
?(unsigned?
long
)p?
-
?(unsigned?
long
)BaseAddr;???
????}
???
????
return
?res;???
}
???
??
//
?創建外殼進程并用目標進程替換它然后執行???
HANDLE?AttachPE(
char
?
*
CmdParam,?PIMAGE_NT_HEADERS?peH,?PIMAGE_SECTION_HEADERS?peSecH,????
????????????????
void
?
*
Ptr,?unsigned?
long
?ImageSize,?unsigned?
long
?
&
ProcId)???

{???
????HANDLE?res?
=
?INVALID_HANDLE_VALUE;???
????CONTEXT?Ctx;???
????HANDLE?Thrd;???
????unsigned?
long
?Addr,?Size;???
????
char
?
*
s?
=
?PrepareShellExe(CmdParam,?peH
->
OptionalHeader.ImageBase,?ImageSize);???
????
if
(s
==
NULL)?
return
?res;???

????
if
(CreateChild(s,?Ctx,?res,?Thrd,?ProcId,?Addr,?Size))
{???
????????
void
?
*
p?
=
?NULL;???
????????unsigned?
long
?old;???

????????
if
((peH
->
OptionalHeader.ImageBase?
==
?Addr)?
&&
?(Size?
>=
?ImageSize))
{
//
?外殼進程可以容納目標進程并且加載地址一致???
????????????p?
=
?(
void
?
*
)Addr;???
????????????VirtualProtectEx(res,?p,?Size,?PAGE_EXECUTE_READWRITE,?
&
old);???
????????}
???

????????
else
?
if
(IsNT())
{???

????????????
if
(UnloadShell(res,?Addr))
{
//
?卸載外殼進程占有內存???
????????????????p?
=
?MyVirtualAllocEx((unsigned?
long
)res,?(
void
?
*
)peH
->
OptionalHeader.ImageBase,?ImageSize,?MEM_RESERVE?
|
?MEM_COMMIT,?PAGE_EXECUTE_READWRITE);???
????????????}
???

????????????
if
((p?
==
?NULL)?
&&
?HasRelocationTable(peH))
{
//
?分配內存失敗并且目標進程支持重定向???
????????????????p?
=
?MyVirtualAllocEx((unsigned?
long
)res,?NULL,?ImageSize,?MEM_RESERVE?
|
?MEM_COMMIT,?PAGE_EXECUTE_READWRITE);???
????????????????
if
(p)?DoRelocation(peH,?Ptr,?p);?
//
?重定向???
????????????}
???
????????}
???

????????
if
(p)
{???
????????????WriteProcessMemory(res,?(
void
?
*
)(Ctx.Ebx
+
8
),?
&
p,?
sizeof
(DWORD),?
&
old);?
//
?重置目標進程運行環境中的基址???
????????????peH
->
OptionalHeader.ImageBase?
=
?(unsigned?
long
)p;???

????????????
if
(WriteProcessMemory(res,?p,?Ptr,?ImageSize,?
&
old))
{
//
?復制PE數據到目標進程???
????????????????Ctx.ContextFlags?
=
?CONTEXT_FULL;???
????????????????
if
((unsigned?
long
)p?
==
?Addr)???
????????????????????Ctx.Eax?
=
?peH
->
OptionalHeader.ImageBase?
+
?peH
->
OptionalHeader.AddressOfEntryPoint;?
//
?重置運行環境中的入口地址???
????????????????
else
??
????????????????????Ctx.Eax?
=
?(unsigned?
long
)p?
+
?peH
->
OptionalHeader.AddressOfEntryPoint;???
????????????????SetThreadContext(Thrd,?
&
Ctx);
//
?更新運行環境???
????????????????ResumeThread(Thrd);
//
?執行???
????????????????CloseHandle(Thrd);???
????????????}
???

????????????
else
{
//
?加載失敗,殺掉外殼進程???
????????????????TerminateProcess(res,?
0
);???
????????????????CloseHandle(Thrd);???
????????????????CloseHandle(res);???
????????????????res?
=
?INVALID_HANDLE_VALUE;???
????????????}
???
????????}
???

????????
else
{
//
?加載失敗,殺掉外殼進程???
????????????TerminateProcess(res,?
0
);???
????????????CloseHandle(Thrd);???
????????????CloseHandle(res);???
????????????res?
=
?INVALID_HANDLE_VALUE;???
????????}
???
????}
???
????delete[]?s;???
????
return
?res;???
}
???
??
??
??
??

?
/**/
/**/
/**/
/*
******************************************************\??
{?*******************************************************?}??
{?*?????????????????從內存中加載并運行exe???????????????*?}??
{?*******************************************************?}??
{?*?參數:????????????????????????????????????????????????}??
{?*?Buffer:?內存中的exe地址???????????????????????????????}??
{?*?Len:?內存中exe占用長度????????????????????????????????}??
{?*?CmdParam:?命令行參數(不包含exe文件名的剩余命令行參數)}??
{?*?ProcessId:?返回的進程Id???????????????????????????????}??
{?*?返回值:?如果成功則返回進程的Handle(ProcessHandle),???}??
{????????????如果失敗則返回INVALID_HANDLE_VALUE???????????}??
{?*******************************************************?}??
?\******************************************************
*/
??
HANDLE?MemExecute(
void
?
*
ABuffer,?
long
?Len,?
char
?
*
CmdParam,?unsigned?
long
?
*
ProcessId)???

{???
????HANDLE?res?
=
?INVALID_HANDLE_VALUE;???
????PIMAGE_NT_HEADERS?peH;???
????PIMAGE_SECTION_HEADERS?peSecH;???
????
void
?
*
Ptr;???
????unsigned?
long
?peSz;???
????
if
(AlignPEToMem(ABuffer,?Len,?peH,?peSecH,?Ptr,?peSz))???

????
{???
????????res?
=
?AttachPE(CmdParam,?peH,?peSecH,?Ptr,?peSz,?
*
ProcessId);???
????????VirtualFree(Ptr,?peSz,?MEM_DECOMMIT);???
????}
???
????
return
?res;???
}
???
??
//
?初始化???
class
?CInit???

{???
public
:???
????CInit()???

????
{???
????????MyVirtualAllocEx?
=
?(pfVirtualAllocEx)GetProcAddress(GetModuleHandle(
"
Kernel32.dll
"
),?
"
VirtualAllocEx
"
);???
????}
???
}
Init;???
??
??
??
??



int
?main(
int
?argc,?
char
*
?argv[])

{
????FILE
*
?fp;
????fp?
=
?fopen(
"
E:\\CProject\\DBGVIEW.EXE
"
,
"
rb
"
);

????
if
?(?fp?)

????
{

????????fseek(fp,
0l
,SEEK_END);

????????
int
?file_size
=
ftell(fp);
/**/
/*
獲取文件長度
*/
????????fseek(fp,
0l
,SEEK_SET);
/**/
/*
回到文件頭部
*/
???
????????
????????
????????LPBYTE?pBuf?
=
?
new
?BYTE[file_size];???
????????memset(?pBuf,?
0
,?file_size);???

????????fread(pBuf,file_size,
1
,fp);

????????DWORD?id?
=
?GetCurrentProcessId();
????????unsigned?
long
?ulProcessId?
=
?
0
;???
????????MemExecute(?pBuf,?file_size,?
""
,?
&
ulProcessId);???
????????delete[]?pBuf;???
????????
????}
??
????
????
return
?
0
;
}