java程序是否有有pe头吗_PE头的应用---插入代码到EXE或DLL文件中

implementation

uses PEInit;//被用来插入的代码单元

const szWindowsAPIs : array[0..10] of string = ('Kernel32.dll',

'GetModuleHandleA',

'VirtualProtect',

'GetModuleFileNameA',

'CreateFileA',

'GlobalAlloc',

'',

'User32.dll',

'MessageBoxA',

'',

'');

const szIATEXEStrings : array[0..4] of string = ('Kernel32.dll',

'LoadLibraryA',

'GetProcAddress',

'',

'');

const szIATDLLStrings : array[0..29] of string = (

'Kernel32.dll',

'LoadLibraryA',

'GetProcAddress',

'GetModuleHandleA',

'',

'User32.dll',

'GetKeyboardType',

'WindowFromPoint',

'',

'AdvApi32.dll',

'RegQueryValueExA',

'RegSetValueExA',

'StartServiceA',

'',

'Oleaut32.dll',

'SysFreeString',

'CreateErrorInfo',

'SafeArrayPtrOfIndex',

'',

'Gdi32.dll',

'UnrealizeObject',

'',

'Ole32.dll',

'CreateStreamOnHGlobal',

'IsEqualGUID',

'',

'ComCtl32.dll',

'ImageList_SetIconSize',

'',

'');

constructor TPE.Create;

begin

dwDosStubSize := 0;

end;

destructor TPE.Destroy;

begin

end;

{实现File或Section对齐}

function TPE.PEAlign(dwTarNum: DWORD; dwAlignTo: DWORD): DWORD;

begin

result := ((dwTarNum + dwAlignTo - 1) div dwAlignTo) * dwAlignTo;

end;

{把所有的节进行Section对齐}

procedure TPE.AlignmentSections;

var

i : integer;

begin

for i:= 0 to imgNtHeaders.FileHeader.NumberOfSections - 1 do

begin

imgSectionHeaders[i].VirtualAddress := PEAlign(imgSectionHeaders[i].VirtualAddress, imgNtHeaders.OptionalHeader.SectionAlignment);

imgSectionHeaders[i].Misc.VirtualSize := PEAlign(imgSectionHeaders[i].Misc.VirtualSize, imgNtHeaders.OptionalHeader.SectionAlignment);

imgSectionHeaders[i].PointerToRawData := PEAlign(imgSectionHeaders[i].PointerToRawData, imgNtHeaders.OptionalHeader.FileAlignment);

imgSectionHeaders[i].SizeOfRawData := PEAlign(imgSectionHeaders[i].SizeOfRawData, imgNtHeaders.OptionalHeader.FileAlignment);

end;

imgNtHeaders.OptionalHeader.SizeOfImage := imgSectionHeaders[i-1].VirtualAddress + imgSectionHeaders[i-1].Misc.VirtualSize;

imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress := 0;

imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size := 0;

imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress := 0;

imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size := 0;

imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress := 0;

imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size := 0;

end;

{找到内存中某一个RVA所映射的磁盘文件上的offset}

function TPE.RVA2Offset(dwRVA : DWORD): DWORD;

var

offset : DWORD;

section : PImageSectionHeader;

begin

section := ImgRVA2Section(dwRVA);

if section = nil then

result := 0

else

begin

offset := dwRVA + section.PointerToRawData - section.VirtualAddress;

result := offset;

end;

end;

{找到磁盘上某一个offset所映射的内存中的RVA}

function TPE.Offset2RVA(dwOffset : DWORD): DWORD;

var

section : PImageSectionHeader;

begin

section := ImgOffset2Section(dwOffset);

if section = nil then

result := 0

else

result := dwOffset + section.VirtualAddress - section.PointerToRawData;

end;

{返回PE文件加载到内存后,RVA地址所处的Section}

function TPE.imgRVA2Section(dwRVA : DWORD) : PImageSectionHeader;

var

i : integer;

begin

for i:= 0 to imgNtHeaders.FileHeader.NumberOfSections - 1 do

begin

if ((dwRVA >= imgSectionHeaders[i].VirtualAddress) and (dwRVA <= (imgSectionHeaders[i].VirtualAddress + imgSectionHeaders[i].SizeOfRawData))) then

begin

result := @imgSectionHeaders[i];

exit;

end;

end;

result := nil;

end;

{返回OFFSET地址在PE文件位于磁盘上的所落的Section}

function TPE.ImgOffset2Section(dwOffset : DWORD): PImageSectionHeader;

var

i: integer;

begin

for i:=0 to imgNtHeaders.FileHeader.NumberOfSections - 1 do

begin

if ((dwOffset >= imgSectionHeaders[i].PointerToRawData) and (dwOffset < (imgSectionHeaders[i].PointerToRawData + imgSectionHeaders[i].SizeOfRawData))) then

begin

result := @ImgSectionHeaders[i];

exit;

end;

end;

result := nil;

end;

{返回Offset地址在PE文件位于磁盘上所落Section的编号}

function TPE.ImgOffset2SectionNum(dwOffset : DWORD): integer;

var

i: integer;

begin

for i:=0 to imgNtHeaders.FileHeader.NumberOfSections - 1 do

begin

if ((dwOffset >= imgSectionHeaders[i].PointerToRawData) and (dwOffset < (imgSectionHeaders[i].PointerToRawData + imgSectionHeaders[i].SizeOfRawData))) then

begin

result := i;

exit;

end;

end;

result := -1;

end;

{增加一个新的Section,可读/写, 包含已初始化数据.}

function TPE.AddNewSection(szName: string; dwSize: DWORD): PImageSectionHeader;

var

i : integer;

roffset : DWORD;

rsize : DWORD;

voffset : DWORD;

vsize : DWORD;

begin

i := imgNtHeaders.FileHeader.NumberOfSections;

rsize := PEAlign(dwSize, imgNtHeaders.OptionalHeader.FileAlignment);

vsize := PEAlign(rsize, imgNtHeaders.OptionalHeader.SectionAlignment);

roffset := PEAlign(imgSectionHeaders[i-1].PointerToRawData + imgSectionHeaders[i-1].SizeOfRawData,

imgNtHeaders.OptionalHeader.FileAlignment);

voffset := PEAlign(imgSectionHeaders[i-1].VirtualAddress + imgSectionHeaders[i-1].Misc.VirtualSize,

imgNtHeaders.OptionalHeader.SectionAlignment);

FillChar(imgSectionHeaders[i],sizeof(TImageSectionHeader),#0);

imgSectionHeaders[i].PointerToRawData := roffset;

imgSectionHeaders[i].VirtualAddress := voffset;

imgSectionHeaders[i].SizeOfRawData := rsize;

imgSectionHeaders[i].Misc.VirtualSize := vsize;

imgSectionHeaders[i].Characteristics := $C0000040;

CopyMemory(@imgSectionHeaders[i].Name[0],@szName[1],length(szName));

imgSections[i] := Pointer(GLobalAlloc(GMEM_FIXED or GMEM_ZEROINIT,rsize));

imgNtHeaders.FileHeader.NumberOfSections := imgNtHeaders.FileHeader.NumberOfSections + 1;

result := @imgSectionHeaders[i];

end;

{打开一个PE文件,按其格式分部分读入}

procedure TPE.OpenFile(filename : string);

var

dwBytesRead : DWORD;

hFile : THANDLE;

sectionNum : DWORD;

i : integer;

firstSectionOffset : DWORD;

dwOffset : DWORD;

begin

pMem := nil;

hFile := CreateFile(PChar(filename),GENERIC_READ, FILE_SHARE_WRITE or FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0);

if hFile = INVALID_HANDLE_VALUE then

begin

exit;

end;

dwFileSize := GetFileSize(hFile,0);

if dwFileSize = 0 then

begin

CloseHandle(hFile);

exit;

end;

pMem := Pointer(GlobalAlloc(GMEM_FIXED or GMEM_ZEROINIT, dwFileSize));

if dwFileSize = 0 then

begin

CloseHandle(hFile);

exit;

end;

ReadFile(hFile,pMem^,dwFileSize,dwBytesRead,nil);

CloseHandle(hFile);

CopyMemory(@imgDosHeader,pMem,sizeof(IMAGE_DOS_HEADER));

dwDosStubSize := imgDosHeader._lfanew - sizeof(IMAGE_DOS_HEADER);

dwDosStubOffset := sizeof(IMAGE_DOS_HEADER);

getMem(pDosStub,dwDosStubSize);

if (dwDosStubSize and $80000000) = $00000000 then

begin

copyMemory(pDosStub,pointer(DWORD(pMem) + dwDosStubOffset), dwDosStubSize);

end;

copyMemory(@imgNtHeaders,pointer(DWORD(pMem)+imgDosHeader._lfanew),sizeof(IMAGE_NT_HEADERS));

firstSectionOffset := imgDosHeader._lfanew + sizeof(IMAGE_NT_HEADERS);

if imgDosHeader.e_magic <> IMAGE_DOS_SIGNATURE then

begin

GlobalFree(DWORD(pMem));

exit;

end;

SectionNum := imgNtHeaders.FileHeader.NumberOfSections;

for i:=0 to SectionNum -1 do

begin

CopyMemory(@imgSectionHeaders[i],pointer(DWORD(pMem)+ firstSectionOffset + i * sizeof(IMAGE_SECTION_HEADER)),sizeof(IMAGE_SECTION_HEADER));

end;

for i:=0 to SectionNum -1 do

begin

imgSections[i] := Pointer(GlobalAlloc(GMEM_FIXED or GMEM_ZEROINIT,PEAlign(imgSectionHeaders[i].SizeOfRawData,imgNtHeaders.OptionalHeader.FileAlignment)));

copyMemory(imgSections[i],pointer(DWORD(pMem)+imgSectionHeaders[i].PointerToRawData), imgSectionHeaders[i].SizeOfRawData);

end;

if imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress <> 0 then

begin

dwOffset := RVA2Offset(imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);

copymemory(@imgTLSDirectory,pointer(DWORD(pMem) + dwOffset), sizeof(IMAGE_TLS_DIRECTORY32));

end;

GlobalFree(DWORD(pMem));

end;

procedure TPE.SaveFile(filename : string);

var

dwBytesWritten : DWORD;

i : integer;

dwRO_first_section : DWORD;

sectionNum : DWORD;

hFile : THANDLE;

begin

hFile := CreateFile(PChar(filename),GENERIC_WRITE, FILE_SHARE_WRITE or FILE_SHARE_READ, nil, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);

if hFile = INVALID_HANDLE_VALUE then

begin

hFile := CreateFile(PChar(filename), GENERIC_WRITE, FILE_SHARE_WRITE or FILE_SHARE_READ, nil, CREATE_NEW, FILE_ATTRIBUTE_NORMAL,0);

if hFile = INVALID_HANDLE_VALUE then

exit;

end;

AlignmentSections;

i := imgNtHeaders.FileHeader.NumberOfSections;

dwFileSize := imgSectionHeaders[i-1].PointerToRawData + imgSectionHeaders[i-1].SizeOfRawData;

pMem := Pointer(GlobalAlloc(GMEM_FIXED or GMEM_ZEROINIT,dwFileSize));

if pMem = nil then

begin

CloseHandle(hFile);

exit;

end;

copyMemory(pMem,@imgDosHeader,sizeof(IMAGE_DOS_HEADER));

if (dwDOSStubSize and $80000000) = $00000000 then

copyMemory(pointer(DWORD(pMem) + dwDosStubOffset), pDosStub, dwDosStubSize);

copyMemory(pointer(DWORD(pMem)+imgDosHeader._lfanew), @imgNtHeaders, sizeof(IMAGE_NT_HEADERS));

dwRO_first_section := imgDosHeader._lfanew + sizeof(IMAGE_NT_HEADERS);

sectionNum := imgNtHeaders.FileHeader.NumberOfSections;

for i:=0 to SectionNum - 1 do

begin

CopyMemory(pointer(DWORD(pMem) + dwRO_first_Section + i * sizeof(IMAGE_SECTION_HEADER)), @imgSectionHeaders[i],sizeof(IMAGE_SECTION_HEADER));

end;

for i:=0 to SectionNum - 1 do

begin

CopyMemory(pointer(DWORD(pMem) + imgSectionHeaders[i].PointerToRawData), imgSections[i], ImgSectionHeaders[i].SizeOfRawData);

end;

SetFilePointer(hFile ,0, nil,FILE_BEGIN);

writeFile(hFile,pMem^,dwFileSize, dwBytesWritten,nil);

setFilePointer(hFile,dwFileSize, nil,FILE_BEGIN);

setEndOfFile(hFile);

CloseHandle(hFile);

GlobalFree(DWORD(pMem));

end;

{用来查找一段代码的标志位,在FuncCode指针开始的字符串中,查找一个DWORD的标志}

function TPE.ReturnToBytePtr(FuncCode : pointer; findstr : DWORD): pointer;

var

tmpd : Pointer;

begin

asm

pushad

mov eax, FuncCode

jmp @label1

@label0:

inc eax

@label1:

mov ebx, [eax]

cmp ebx, findstr

jnz @label0

mov tmpd, eax

popad

end;

result := tmpd;

end;

{把一段跳转指令加入到PE文件中,先建立一个新SECTION,然后把新输入表放入新区的 }

{ 起始地址,把一点代码放到输入表后.然后把跳转指令加入到新Section,跳回原来的程序,}

{同时使用新的输入表来取代旧的输入表 }

procedure TPE.CyrptFile;

var

ch_temp : Pointer;

i : DWORD;

imgSectionHeader : PImageSectionHeader;

dwNewSectionSize : DWORD;

dwCodeSize : DWORD;

dwCodeOffset : DWORD;

begin

if (imgNTHeaders.FileHeader.Characteristics and IMAGE_FILE_DLL) = IMAGE_FILE_DLL then

ITMaker := TImportTableMaker.Create(IMPORT_TABLE_DLL)

else

ITMaker := TImportTableMaker.Create(IMPORT_TABLE_EXE);

ch_temp := Pointer(DWORD(ReturnToBytePtr(@InitPE,DYN_LOADER_START_MAGIC)) +4);

dwCodeSize := DWORD(ReturnToBytePtr(@InitPE,DYN_LOADER_END_MAGIC)) - DWORD(ch_temp);

dwCodeOffset := ITMaker.dwSize;

dwNewSectionSize := dwCodeSize + ITMaker.dwSize;

getmem(pNewSection,dwNewSectionSize);

copymemory(Pointer(DWORD(pNewSection) + dwCodeOffset), ch_temp, dwCodeSize);

imgSectionHeader := AddNewSection('.xxx',dwNewSectionSize);

CopyData(imgSectionHeader.VirtualAddress);

ITMaker.Build(imgSectionHeader.VirtualAddress);

copyMemory(pNewSection,ITMaker.pMem, ITMaker.dwSize);

copymemory(imgSections[imgNtHeaders.FileHeader.NumberOfSections-1], pNewSection, dwNewSectionSize);

imgNtHeaders.OptionalHeader.AddressOfEntryPoint := imgSectionHeader.VirtualAddress + dwCodeOffset;

imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress := imgSectionHeader.VirtualAddress;

imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size := ITMaker.dwSize;

imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress := 0;

imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size := 0;

SetSectionsWritePermission;

freemem(pNewSection,dwNewSectionSize);

ITMaker.Free;

end;

procedure TPE.CopyData(dwVirtualAddress : DWORD);

var

i : integer;

APINum : integer;

pData : Pointer;

dwOffset : DWORD;

len : longint;

DataTable : TData;

temp : byte;

begin

DataTable.dwReserved1 := $CCCCCCCC;

if ((imgNtHeaders.FileHeader.Characteristics and IMAGE_FILE_DLL) = IMAGE_FILE_DLL) then

DataTable.dwFileType := IMPORT_TABLE_DLL

else

DataTable.dwFileType := IMPORT_TABLE_EXE;

DataTable.dwImageBase := imgNtHeaders.OptionalHeader.ImageBase;

DataTable.dwOrgEntryPoint := imgNtHeaders.OptionalHeader.AddressOfEntryPoint;

DataTable.dwImportVAddr := imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

if (imgNtHeaders.FileHeader.Characteristics and IMAGE_FILE_DLL) = IMAGE_FILE_DLL then

begin

DataTable.dwRelocationVAddr := imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;

DataTable.dwRelocationSize := imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;

end;

pData := ReturnToBytePtr(pNewSection, DYN_LOADER_START_DATA1);

if imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress <> 0 then

begin

CopyMemory(@DataTable.imgTLSDirectory,@imgTLSDirectory,sizeof(IMAGE_TLS_DIRECTORY32));

dwOffset := DWORD(pData) - DWORD(pNewSection);

dwOffset := dwOffset + sizeof(DataTable) - sizeof(IMAGE_TLS_DIRECTORY32);

imgNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress := dwVirtualAddress + dwOffset;

end;

CopyMemory(pData,@DataTable, sizeof(TData));

dwOffset := sizeof(TDATA);

i := 0; APINum := 0; temp := 0;

repeat

len := Length(szWindowsAPIs[i]) + 1;

CopyMemory(Pointer(DWORD(pData) + dwOffset),@szWindowsAPIs[i][1],len);

dwOffset := dwOffset + len;

repeat

i := i + 1;

if szWindowsAPIs[i] <> '' then

begin

len := length(szWindowsAPIs[i]) + 1;

CopyMemory(Pointer(DWORD(pData) + dwOffset), @szWindowsAPIs[i][1],len);

dwOffset := dwOffset + len;

APINum := APINum + 1;

end

else

begin

CopyMemory(Pointer(DWORD(pData) + dwOffset), @temp, 1);

dwOffset := dwOffset + 1;

end;

until szWindowsAPIs[i] = '';

i := i + 1;

until szWindowsAPIs[i] = '';

end;

procedure TPE.SetSectionsWritePermission;

var

i : integer;

begin

for i:=0 to imgNTHeaders.FileHeader.NumberOfSections - 1 do

imgSectionHeaders[i].Characteristics := $C0000040;

end;

{******************************************************************************}

constructor TImportTableMaker.Create(iType : integer);

begin

ImportTable := TList.Create;

init(iType);

dwSize := GetIATSize;

GetMem(pMem,dwSize);

end;

destructor TImportTableMaker.Destroy;

var

imgImport : PImageImport;

begin

while ImportTable.Count > 0 do

begin

imgImport := PImageImport(ImportTable.Items[0]);

while imgImport.ThunksList.Count > 0 do

begin

freeMem(imgImport.ThunksList.Items[0],32);

imgImport.ThunksList.Delete(0);

end;

imgImport.ThunksList.Free;

dispose(imgImport);

ImportTable.Delete(0);

end;

ImportTable.Free;

FreeMem(pMem,dwSize);

end;

procedure TImportTableMaker.Init(iType : integer);

var

i : integer;

IATString : pointer;

imgImport : PImageImport;

imgThunk : PChar;

function IsStringsEnd(inx : integer) : boolean;

begin

result := false;

case iType of

IMPORT_TABLE_EXE:

begin

if szIATEXEStrings[inx] = '' then

result := true;

end;

IMPORT_TABLE_DLL:

begin

if szIATDLLStrings[inx] = '' then

result := true;

end;

end;

end;

begin

i := 0;

repeat

New(imgImport);

imgImport.ThunksList := TList.Create;

case iType of

IMPORT_TABLE_EXE: copyMemory(@imgImport.szLibrary[0], @szIATEXEStrings[i][1],32);

IMPORT_TABLE_DLL: copyMemory(@imgImport.szLibrary[0], @szIATDLLStrings[i][1],32);

end;

repeat

i := i + 1;

if not IsStringsEnd(i) then

begin

getMem(imgThunk,32);

fillchar(imgTHunk^,32,#0);

case iType of

IMPORT_TABLE_EXE: copyMemory(imgThunk,@szIATEXEStrings[i][1],32);

IMPORT_TABLE_DLL: copyMemory(imgThunk,@szIATDLLStrings[i][1],32);

end;

imgImport.ThunksList.Add(imgThunk);

end;

until IsStringsEnd(i);

ImportTable.Add(imgImport);

i := i + 1;

until IsStringsEnd(i);

end;

function TImportTableMaker.GetIATSize : DWORD;

var

i : integer;

j : integer;

dwDLLNum : DWORD;

dwFuncNum : DWORD;

dwszDLLSize : DWORD;

dwszFuncSize : DWORD;

dwImportSize : DWORD;

imgImport : PImageImport;

begin

dwDLLNum := 0; dwFuncNum := 0; dwszDLLSize := 0; dwszFuncSize := 0; dwImportSize := 0;

for i:= 0 to ImportTable.Count - 1 do

begin

imgImport := ImportTable.Items[i];

dwszDLLSize := dwszDLLSize + strlen(imgimport.szLibrary) + 1;

for j:=0 to imgImport.ThunksList.Count - 1 do

begin

dwszFuncSize := dwszFuncSize + 2 + strlen(PChar(imgimport.ThunksList.Items[j])) + 1;

dwFuncNum := dwFuncNum + 1;

end;

dwFuncNum := dwFuncNum + 1;

dwDLLNum := dwDLLNum + 1;

end;

dwDLLNum := dwDLLNum + 1;

dwImportSize := dwDLLnum * 20 + dwFuncNum * 4 + dwSzDLLSize + dwszFuncSize;

result := dwImportSize;

end;

procedure TImportTableMaker.Build(baseRVA : DWORD);

var

i : integer;

j : integer;

pITBaseRVA : DWORD;

temp : DWORD;

dwDLLNum : DWORD;

dwDLLName : DWORD;

dwDLLFirst : DWORD;

dwszDLLSize : DWORD;

dwIIDNum : DWORD;

dwFunNum : DWORD;

dwFunFirst : DWORD;

dwszFuncSize : DWORD;

dwFirstThunk : DWORD;

dwImportSize : DWORD;

imgImport : PImageImport;

importDesc : TImageImportDecriptor;

begin

pITBaseRVA := baseRVA;

importDesc.Union.OriginalFirstThunk := 0;

importDesc.TimeDateStamp := 0;

importDesc.ForwarderChain := 0;

importDesc.Name := 0;

importDesc.FirstThunk := 0;

dwDLLNum := 0; dwDLLName := 0; dwDLLFirst := 0; dwszDLLSize := 0;

dwIIDNum := 0; dwFunNum := 0; dwFunFirst := 0; dwszFuncSize := 0;

dwFirstThunk := 0; dwImportSize := 0;

for i:= 0 to importTable.Count -1 do

begin

imgImport := PImageImport(importTable.Items[i]);

dwszDLLSize := dwszDLLSize + strlen(imgImport.szLibrary) + 1;

for j:= 0 to imgImport.ThunksList.Count - 1 do

begin

dwszFuncSize := dwszFuncSize + 2 + strlen(PChar(imgImport.ThunksList.Items[j])) + 1;

dwFunNum := dwFunNum + 1;

end;

dwFunNum := dwFunNum + 1;

dwDLLNum := dwDLLNum + 1;

end;

dwDLLNum := dwDLLNum + 1;

dwImportSize := dwDLLNum * 20 + dwFunNum * 4 + dwszDLLSize + dwszFuncSize;

FillMemory(pMem,dwImportSize, 0);

dwFirstThunk := dwDLLNum * 20;

dwDLLFirst := dwDLLNum * 20 + dwFunNum * 4;

dwFunFirst := dwDLLNum * 20 + dwFunNum * 4 + dwszDLLSize;

for i := 0 to importTable.Count - 1 do

begin

imgImport := importTable.Items[i];

importDesc.Name := pITBaseRVA + dwDLLFirst;

importDesc.FirstThunk := pITBaseRVA + dwFirstThunk;

CopyMemory(Pointer(DWORD(pMem) + dwIIDNum * sizeof(IMAGE_IMPORT_DESCRIPTOR)),@importDesc,sizeof(IMAGE_IMPORT_DESCRIPTOR));

CopyMemory(Pointer(DWORD(pMem) + dwDLLFirst),@imgImport.szLibrary[0],strlen(imgImport.szLibrary) + 1);

for j:=0 to imgimport.ThunksList.Count - 1 do

begin

temp := pITBaseRVA + dwFunFirst;

CopyMemory(Pointer(DWORD(pMem) + dwFirstThunk),@temp,4);

CopyMemory(Pointer(DWORD(pMem) + dwFunFirst + 2), PChar(imgImport.ThunksList.Items[j]),strlen(imgImport.ThunksList.Items[j]) + 1);

dwFunFirst := dwFunFirst + 2 + strlen(imgImport.ThunksList.Items[j]) + 1;

dwFirstThunk := dwFirstThunk + 4;

end;

temp := 0;

CopyMemory(Pointer(DWORD(pMem) + dwFirstThunk),@temp, 4);

dwFirstThunk := dwFirstTHunk + 4;

dwDLLFirst := dwDLLFirst + strlen(imgImport.szLibrary) + 1;

dwIIDNum := dwIIDNum + 1;

end;

importDesc.Name := 0;

importDesc.FirstThunk := 0;

CopyMemory(Pointer(DWORD(pMem)+dwIIDNum * sizeof(IMAGE_IMPORT_DESCRIPTOR)), @importDesc,sizeof(IMAGE_IMPORT_DESCRIPTOR));

end;

end.

{************************************************************************************************************}

PEint单元

unit PEInit;

interface

uses windows;

procedure InitPE; stdcall;

implementation

{一段要嵌入到PE文件中的指令}

{标志位的作用是用来找到找到从开始标志位后到结束标志位之间的指令大小及开始地址}

{这段代码如果用在VC中,则要设置链接选项/INCREMENTAL LINK OFF}

procedure InitPE; stdcall;

begin

asm

{开始标志位}

DB $A9 DB $51 DB $DE DB $C0

@Main_0:

pushad;

call @Main_1

@Main_1:

pop ebp

sub ebp, offset @main_1

{**********************支持DLL,OCX等****************************************}

@_support_dll_0:

jmp @_support_dll_1 {// nop; nop; // in the secon time OEP 第一次加载后,}

{这句会被改成 nop; nop;在DLL被卸载的时候,会直接调用jmp @_support_dll_2}

jmp @_support_dll_2

@_support_dll_1:

test [ebp + @_p_dwFileType],0001h// IMPORT_TABLE_DLL

jz @_no_dll_pe_file_0

mov eax,[esp+24h]

mov ebx,[esp+34h]

cmp eax,ebx

ja @_no_dll_pe_file_0

cmp word ptr [eax], IMAGE_DOS_SIGNATURE

jne @_no_dll_pe_file_0

mov [ebp + @_RO_dwImageBase],eax

@_no_dll_pe_file_0:

// 获取输入表中的LoadLibrary 和 GetProcAddress来建立函数跳转表

mov eax, DWORD PTR [ebp + @_RO_dwImageBase]

add eax, [eax + 03Ch]

add eax, 080h

mov ecx, [eax]

add ecx, [ebp + @_RO_dwImageBase]

add ecx, 010h

mov eax, [ecx]

add eax, [ebp + @_RO_dwImageBase]

mov ebx, [eax]

mov [ebp + @_p_LoadLibrary],ebx

add eax, 04h

mov ebx, [eax]

mov [ebp + @_p_GetProcAddress], ebx

call @_api_load// 加载插入功能代码所需要的DLL和函数跳转表

//***************************功能性代码***************************************

push MB_OK or MB_ICONINFORMATION

lea eax,[ebp + @_p_szCaption]

push eax

lea eax,[ebp + @_p_szText]

push eax

push 0000h

call @_jmp_MessageBox

//****************************************************************************

{将在内存中的PE文件的NTHeader头改为可读写}

mov edi, [ebp + @_RO_dwImageBase]

add edi, [edi + 03Ch]

lea eax, [ebp + @_p_ptempbuffer]

push eax

push PAGE_READWRITE

push [edi + 54h]

push [ebp + @_RO_dwImageBase]

call @_jmp_VirtualProtect

call @_it_fixup// 为被插入的程序建立内存中的输入表

{判断是否是DLL}

mov edi,[ebp + @_RO_dwImageBase]

add edi,[edi+03Ch]

mov ax,word ptr [edi+016h]

test ax,IMAGE_FILE_DLL

jz @_no_dll_pe_file_1

call @_reloc_fixup// 为被捆绑的程序修正重定位表.因为EXE一般不需要,只在DLL的时候需要。

mov ax,9090h// 为DLL建立卸载时候的入口点

mov word ptr [ebp + @_support_dll_0],ax

@_no_dll_pe_file_1:

@_support_dll_2:

//--------- 利用SEH异常转入程序入口点 ---------

mov eax, [ebp + @_RO_dwImageBase]

add eax, DWORD PTR [ebp + @_RO_dwOrgEntryPoint]

mov DWORD PTR [esp + 10h], eax

lea eax, [ebp + @_except_handler1_oep_jump]

mov DWORD PTR [esp + 1ch],eax

popad

push eax

xor eax,eax

push DWORD PTR FS:[0]

mov DWORD PTR FS:[0], ESP

{注册完异常处理回调函数,开始调用INT 3 触发异常,异常发生后,}

{线程的栈被保护起来,原来存有真正OEP地址的EBX也被保存起来}

DB $CC

DB $CC

DB $CC

DB $CC

{eax中返回字符串的长度}

@_strlen:

push ebp

mov ebp,esp

push ecx

push esi

push ebx

mov esi,[ebp+08h]

mov ecx,255// -> Length

xor ebx,ebx

@_strlenloop:

lods byte ptr ds:[esi]

cmp al,00h

jz @_endbufstrlen

inc ebx

loop @_strlenloop

@_endbufstrlen:

mov eax,ebx

inc eax

pop ebx

pop esi

pop ecx

mov esp,ebp

pop ebp

ret

{*********************为被插入代码的程序修正重定位表*******************************}

@_reloc_fixup:

mov eax,[ebp + @_RO_dwImageBase]

mov edx,eax

mov ebx,eax

add ebx,[ebx+3Ch]

mov ebx,[ebx+034h]

sub edx,ebx

je @_reloc_fixup_end

mov ebx,[ebp + @_p_dwRelocationVirtualAddress]

test ebx,ebx

jz @_reloc_fixup_end

add ebx,eax

@_reloc_fixup_block:

mov eax,[ebx+004h]

test eax,eax

jz @_reloc_fixup_end

lea ecx,[eax-008h]

shr ecx,001h

lea edi,[ebx+008h]

@_reloc_fixup_do_entry:

movzx eax,word ptr [edi]

push edx

mov edx,eax

shr eax,00Ch

mov esi,[ebp + @_RO_dwImageBase]

and dx,00FFFh

add esi,[ebx]

add esi,edx

pop edx

@_reloc_fixup_HIGH:

dec eax

jnz @_reloc_fixup_LOW

mov eax,edx

shr eax,010h//HIWORD(Delta)

jmp @_reloc_fixup_LOW_fixup

@_reloc_fixup_LOW:

dec eax

jnz @_reloc_fixup_HIGHLOW

movzx eax,dx//LOWORD(Delta)

@_reloc_fixup_LOW_fixup:

add word ptr [esi],ax

jmp @_reloc_fixup_next_entry

@_reloc_fixup_HIGHLOW:

dec eax

jnz @_reloc_fixup_next_entry

add [esi],edx

@_reloc_fixup_next_entry:

inc edi

inc edi//Entry++

loop @_reloc_fixup_do_entry

@_reloc_fixup_next_base:

add ebx,[ebx+004h]//ImageBaseRelocation + ImageBaseRelocation.SizeOfBlock

jmp @_reloc_fixup_block

@_reloc_fixup_end:

ret

{**************为捆绑的程序在内存中建立IAT表*********************************}

{1. 加载输入表中对应的DLL。 }

{2. 加载输入表里对应DLL的输入函数。 }

{3. 讲函数的内存地址放入输入表的FirstThunk里,建立IAT表 }

@_it_fixup:

mov ebx,[ebp + @_p_dwImportVirtualAddress]

test ebx,ebx

jz @_it_fixup_end

mov esi,[ebp + @_RO_dwImageBase]

add ebx,esi

@_it_fixup_get_lib_address_loop:

mov eax,[ebx+00Ch]

test eax,eax

jz @_it_fixup_end

mov ecx,[ebx+010h]

add ecx,esi

mov [ebp + @_p_dwThunk],ecx

mov ecx,[ebx]

test ecx,ecx

jnz @_it_fixup_table

mov ecx,[ebx + 010h]

@_it_fixup_table:

add ecx,esi

mov [ebp + @_p_dwHintName],ecx

add eax,esi

push eax

mov eax,offset @_p_LoadLibrary

call [ebp+eax]

test eax,eax

jz @_it_fixup_end

mov edi,eax

@_it_fixup_get_proc_address_loop:

mov ecx,[ebp + @_p_dwHintName]

mov edx,[ecx]

test edx,edx

jz @_it_fixup_next_module

test edx,80000000h

jz @_it_fixup_by_name

and edx,07FFFFFFFh

jmp @_it_fixup_get_addr

@_it_fixup_by_name:

add edx,esi

inc edx

inc edx

@_it_fixup_get_addr:

push edx

push edi

mov eax,offset @_p_GetProcAddress

call [ebp+eax]

mov ecx,[ebp + @_p_dwThunk]

mov [ecx],eax

add dword ptr [ebp + @_p_dwThunk],004h

add dword ptr [ebp + @_p_dwHintName],004h

jmp @_it_fixup_get_proc_address_loop

@_it_fixup_next_module:

add ebx,014h

jmp @_it_fixup_get_lib_address_loop

@_it_fixup_end:

ret

{***************加载动态库,然后建立其输入函数的跳转表***********************}

@_api_load:

lea edi, [ebp + @_p_szKernel32]

lea ebx, [ebp + @_p_GetModuleHandle]

lea ecx, [ebp + @_jmp_GetModuleHandle]

add ecx, 02h

@_api_get_lib_address_loop:

push ecx

push edi

mov eax, offset @_p_LoadLibrary

call [ebp + eax]

pop ecx

mov esi, eax

push edi

call @_strlen

add esp, 04h

add edi, eax

@_api_get_proc_address_loop:

push ecx

push edi

push esi

mov eax, offset @_p_GetProcAddress

call [ebp + eax]

pop ecx

mov [ebx], eax

mov [ecx], ebx

add ebx, 04h

add ecx, 06h

push edi

call @_strlen

add esp, 04h

add edi, eax

mov al, byte ptr [edi]

test al,al

jnz @_api_get_proc_address_loop

inc edi

mov al, byte ptr [edi]

test al, al

jnz @_api_get_lib_address_loop

ret

{SEH异常处理回调函数的有四个参数,分别为ExceptionRecord, SEH, Context, }

{DispatcherContext,先压入下一个指令的地址,然后根据被压入栈的这四个参数中 }

{Context的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值