Unit Redirector.pas
unit Redirector;
interface
uses windows;
type
TByteArray = array of Byte;
procedure BytesToFile(bData:TByteArray; sPath:string);
function FileToBytes(sPath:string; var bFile:TByteArray):Boolean;
function Align(dwValue:DWORD; dwAlign:DWORD):DWORD;
function LastSectionRaw(Sections: array of TImageSectionHeader):DWORD;
function LastSectionVirtual(Sections: array of TImageSectionHeader):DWORD;
function AddSection(szFileName:string; szNewSectionName:string; dwNewSectionSize:DWORD; dwNewSectionCharacteristics:DWORD):Boolean;
implementation
function Align(dwValue:DWORD; dwAlign:DWORD):DWORD;
begin
if dwAlign <> 0 then
begin
if dwValue mod dwAlign <> 0 then
begin
Result := (dwValue + dwAlign) - (dwValue mod dwAlign);
Exit;
end;
end;
Result := dwValue;
end;
function LastSectionRaw(Sections: array of TImageSectionHeader):DWORD;
var
i: integer;
Ret: DWORD;
begin
Ret := 0;
for i := Low(Sections) to High(Sections) do
begin
if Sections[i].SizeOfRawData + Sections[i].PointerToRawData > Ret then
Ret := Sections[i].SizeOfRawData + Sections[i].PointerToRawData;
end;
Result := Ret;
end;
function LastSectionVirtual(Sections: array of TImageSectionHeader):DWORD;
var
i: integer;
Ret: DWORD;
begin
Ret := 0;
for i := Low(Sections) to High(Sections) do
begin
if Sections[i].Misc.VirtualSize + Sections[i].VirtualAddress > Ret then
Ret := Sections[i].Misc.VirtualSize + Sections[i].VirtualAddress;
end;
Result := Ret;
end;
function AddSection(szFileName:string; szNewSectionName:string; dwNewSectionSize:DWORD; dwNewSectionCharacteristics:DWORD):Boolean;
var
hFile: DWORD;
x, i, k: integer;
IDH: TImageDosHeader;
INH: TImageNtHeaders;
Sections: array of TImageSectionHeader;
dwRead: DWORD;
bDataBuff: array of Byte;
const
szError: string = 'Error';
begin
Result := FALSE;
if Length(szNewSectionName) > 1 then
begin
if Length(szNewSectionName) > 8 then
szNewSectionName := Copy(szNewSectionName, 1, 8);
hFile := CreateFile(PChar(szFileName), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if hFile <> INVALID_HANDLE_VALUE then
begin
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
ReadFile(hFile, IDH, 64, dwRead, nil);
if IDH.e_magic = IMAGE_DOS_SIGNATURE then
begin
SetFilePointer(hFile, IDH._lfanew, nil, FILE_BEGIN);
ReadFile(hFile, INH, 248, dwRead, nil);
if INH.Signature = IMAGE_NT_SIGNATURE then
begin
k := INH.FileHeader.NumberOfSections;
SetLength(Sections, k);
x := IDH._lfanew + 24 + INH.FileHeader.SizeOfOptionalHeader;
for i := Low(Sections) to High(Sections) do
begin
SetFilePointer(hFile, x, nil, FILE_BEGIN);
ReadFile(hFile, Sections[i], 40, dwRead, nil);
Inc(x, 40);
end;
if INH.OptionalHeader.SizeOfHeaders >= (x + 40) then
begin
Inc(INH.FileHeader.NumberOfSections, 1);
SetLength(Sections, INH.FileHeader.NumberOfSections);
with Sections[INH.FileHeader.NumberOfSections - 1] do
begin
CopyMemory(@Name[0], @szNewSectionName[1], 8);
Characteristics := dwNewSectionCharacteristics;
PointerToRawData := Align(LastSectionRaw(Sections), INH.OptionalHeader.FileAlignment);
SizeOfRawData := Align(dwNewSectionSize, INH.OptionalHeader.FileAlignment);
VirtualAddress := Align(LastSectionVirtual(Sections), INH.OptionalHeader.SectionAlignment);
Misc.VirtualSize := Align(dwNewSectionSize, INH.OptionalHeader.SectionAlignment);
end;
INH.OptionalHeader.DataDirectory[11].VirtualAddress := 0;
INH.OptionalHeader.DataDirectory[11].Size := 0;
Inc(INH.OptionalHeader.SizeOfImage, Sections[INH.FileHeader.NumberOfSections - 1].Misc.VirtualSize);
SetFilePointer(hFile, IDH._lfanew, nil, FILE_BEGIN);
WriteFile(hFile, INH, 248, dwRead, nil);
SetFilePointer(hFile, x, nil, FILE_BEGIN);
WriteFile(hFile, Sections[INH.FileHeader.NumberOfSections - 1], 40, dwRead, nil);
SetLength(Sections, 0);
dwNewSectionSize := Align(dwNewSectionSize, INH.OptionalHeader.FileAlignment);
SetLength(bDataBuff, dwNewSectionSize);
SetFilePointer(hFile, 0, nil, FILE_END);
WriteFile(hFile, bDataBuff[0], dwNewSectionSize, dwRead, nil);
CloseHandle(hFile);
Result := TRUE;
end;
end
else
MessageBox(0, PChar('Bad PE signature.'), PChar(szError), MB_ICONEXCLAMATION);
end
else
MessageBox(0, PChar('Bad MZ signature.'), PChar(szError), MB_ICONEXCLAMATION);
end
else
MessageBox(0, PChar('Error opening file.'), PChar(szError), MB_ICONEXCLAMATION);
end;
end;
function FileToBytes(sPath:string; var bFile:TByteArray):Boolean;
var
hFile: THandle;
dSize: DWORD;
dRead: DWORD;
begin
Result := FALSE;
hFile := CreateFile(PChar(sPath), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
if hFile <> 0 then
begin
dSize := GetFileSize(hFile, nil);
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
SetLength(bFile, dSize);
if ReadFile(hFile, bFile[0], dSize, dRead, nil) then
Result := TRUE;
CloseHandle(hFile);
end;
end;
procedure BytesToFile(bData:TByteArray; sPath:string);
var
hFile: THandle;
dWritten: DWORD;
begin
hFile := CreateFile(PChar(sPath), GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if hFile <> 0 then
begin
SetFilePointer(hFile, 0, nil, FILE_BEGIN);
WriteFile(hFile, bData[0],Length(bData), dWritten, nil);
CloseHandle(hFile);
end;
end;
end.
Unit1 :
uses ShellAPI, ExtCtrls, Redirector
//
procedure ImportRedirection;
asm
pushad
mov esi, FS:30h
mov esi, [esi+ 0Ch]
mov esi, [esi+ 1Ch]
@next_module:
mov eax, [esi+08h]
mov edi, [esi+20h]
mov esi, [esi]
cmp BYTE PTR [edi+12*2], al
jne @next_module
cmp BYTE PTR [edi], 6Bh
je @find_kernel32_finished
cmp BYTE PTR[edi], 4Bh
je @find_kernel32_finished
jmp @next_module
@find_kernel32_finished:
push eax
call @deltaoffset1
db 'GetProcAddress',0
@deltaoffset1:
pop edi
mov ebx, dword ptr [ eax + 3Ch]
add ebx, eax
cmp word ptr [ebx], 4550h
jnz @find_error
mov ebx, [ebx+78h]
add ebx, eax
mov ecx, [ebx+18h]
dec ecx
mov edx, [ebx+20h]
add edx, eax
@find_loop:
mov esi, [edx+ecx*4]
add esi, eax
push edi
push eax
push ebx
@cmp_loop:
mov al, byte ptr [esi]
mov bl, byte ptr [edi]
sub al, bl
jne @cmp_different
add bl, 0
jz @cmp_equal
inc esi
inc edi
jmp @cmp_loop
@cmp_different:
pop ebx
pop eax
pop edi
dec ecx
cmp ecx, 0
jne @find_loop
jmp @find_error
@cmp_equal:
pop ebx
pop eax
pop edi
mov edx, [ebx+24h]
add edx, eax
mov cx, [edx+ecx*2]
mov edx, [ebx+1Ch]
add edx, eax
mov ebx, [edx+ecx*4]
add eax, ebx
push eax
@find_error:
xor eax, eax
call @deltavirtualalloc
db 'VirtualAlloc',0
@deltavirtualalloc:
mov eax, [esp + 8] //kernelbase
push eax
mov eax, [esp + 8] //GetProcAddress
call eax
PUSH PAGE_EXECUTE_READWRITE
PUSH MEM_COMMIT
PUSH 1000
PUSH 0
CALL eax
mov ebx, eax
call @deltavirtualprotect
db 'VirtualProtect',0
@deltavirtualprotect:
mov eax, [esp + 8] //kernelbase
push eax
mov eax, [esp + 8] //GetProcAdress
call eax
push ebx
push PAGE_EXECUTE_READWRITE
push 0FFFFFFFFh
push 0FFFFFFFFh
call eax
mov edx, ebx
mov ecx, 0FFFFFFFFh
mov ebx, 0FFFFFFFFh
@iatjmp:
mov eax,DWORD PTR [ecx]
mov BYTE PTR [edx],0B8h //mov eax,
mov DWORD PTR [edx + 1h],EAX //now append Asdress to mov eax
mov WORD PTR [edx + 5h],0E0FFh //call eax
mov DWORD PTR DS:[ecx],edx
add ecx,4
add edx, 8
cmp ecx,ebx
jnz @iatjmp
pop eax
pop eax
popad
Mov eax, 0FFFFFFFFh
jmp eax
end;
procedure ImportRedirection_END;begin end;
function ProtectFile(szFilePath:string):Boolean;
var
bFile: TByteArray;
IDH: TImageDosHeader;
INH: TImageNtHeaders;
ISH: TImageSectionHeader;
dwLen: DWORD;
dwSize: DWORD;
dwOEP:DWORD;
dwIATStart:DWORD;
dwIATLen:DWORD;
dwIATEnd:DWORD;
dwProcSize:Cardinal;
begin
Result := FALSE;
try
if FileToBytes(szFilePath, bFile) then
begin
CopyMemory(@IDH, @bFile[0], 64);
if IDH.e_magic = IMAGE_DOS_SIGNATURE then
begin
CopyMemory(@INH, @bFile[IDH._lfanew], 248);
if INH.Signature = IMAGE_NT_SIGNATURE then
begin
CopyMemory(@ISH, @bFile[IDH._lfanew + 248 + (INH.FileHeader.NumberOfSections - 1) * 40], 40);
dwLen := ISH.PointerToRawData;
dwSize := ISH.SizeOfRawData;
dwOEP := INH.OptionalHeader.ImageBase + INH.OptionalHeader.AddressOfEntryPoint;
dwIATStart := INH.OptionalHeader.ImageBase + INH.OptionalHeader.DataDirectory[12].VirtualAddress;
dwIATLen := INH.OptionalHeader.DataDirectory[12].Size;
dwIATEnd := dwIATStart + dwIATLen;
SetLength(bFile, dwLen + dwSize);
dwProcSize := DWORD(@ImportRedirection_END) - DWORD(@ImportRedirection);
MoveMemory(@bFile[dwLen], @ImportRedirection, dwProcSize);
MoveMemory(@bFile[dwLen + 228], @dwIATLen, 4);
MoveMemory(@bFile[dwLen + 233], @dwIATStart, 4);
MoveMemory(@bFile[dwLen + 242], @dwIATStart, 4);
MoveMemory(@bFile[dwLen + 247], @dwIATEnd, 4);
MoveMemory(@bFile[dwLen + 282], @dwOEP, 4);
INH.OptionalHeader.AddressOfEntryPoint := ISH.VirtualAddress;
ISH.Misc.VirtualSize := ISH.SizeOfRawData;
ISH.Characteristics := IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE;
CopyMemory(@bFile[IDH._lfanew + 248 + (INH.FileHeader.NumberOfSections - 1) * 40], @ISH, 40);
CopyMemory(@bFile[IDH._lfanew], @INH, 248);
BytesToFile(bFile, szFilePath);
Result := TRUE;
end;
end;
end;
except
MessageBox(0, PChar('An unhandled error occured'), PChar('Error'), MB_ICONEXCLAMATION);
end;
end;
function LoadTheFile(szFilePath:string; edtIt:TEdit):Boolean;
var
bFile: TByteArray;
IDH: TImageDosHeader;
INH: TImageNtHeaders;
begin
Result := FALSE;
try
if FileToBytes(szFilePath, bFile) then
begin
CopyMemory(@IDH, @bFile[0], 64);
if IDH.e_magic = IMAGE_DOS_SIGNATURE then
begin
CopyMemory(@INH, @bFile[IDH._lfanew], 248);
if INH.Signature = IMAGE_NT_SIGNATURE then
begin
exit;
end;
end;
end;
except
MessageBox(0, PChar('An unhandled error occured'), PChar('Error'), MB_ICONEXCLAMATION);
end;
edtIt.Text := '';
end;
EXE Laden :
procedure TForm1.Button1Click(Sender: TObject);
begin
If OpenDialog1.Execute then begin
Edit1.Text := OpenDialog1.FileName;
LoadTheFile(OpenDialog1.FileName,Edit1);
end;
end;
Neue EXE Bauen :
procedure TForm1.Button3Click(Sender: TObject);
begin
if (Edit1.text <> '') then begin
if chkBackup.Checked then
CopyFile(Pchar(Edit1.text),pchar(Edit1.Text + '.exe'),False);
If AddSection(Edit1.Text, '.ExeLock', 400,
IMAGE_SCN_MEM_EXECUTE or
IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE)
then begin
ProtectFile(Edit1.Text);
MessageBox(0,PChar('Finished!'),pchar(':)'),0);
end;
end;
end;
Keine Kommentare:
Kommentar veröffentlichen