📄 dedesym.pas
字号:
unit DeDeSym;
//////////////////////////
// Last Change: 21.II.2001
//////////////////////////
interface
Uses Classes, DeDeClasses, DeDeConstants;
// DeDe Symbols ///////////////////////////////////////////////////////
Type TDeDeSymbol = Class
protected
procedure UpdateFirstByteSet;
public
Sym : TMemoryStream;
Str : TMemoryStream;
Index : Array of Integer;
Count : Integer;
Comment : String;
Mode : Byte;
PatternSize : Byte;
FileName : String;
Constructor Create; virtual;
Function LoadSymbol(AsFileName : String) : Boolean;
Destructor Destroy; override;
End;
Function UnlinkCalls(Var buff : TSymBuffer; Level : byte = 0; RVA : DWORD = 0) : Boolean;
Function GetDSFVersion(Sym : TDeDeSymbol) : String;
procedure ParseExportName(var sExport : String);
procedure ParseExportParam(var sParam : String);
procedure ParseExportParamFlags(sFlags : String; var beg, en : String);
function DCUFixParams(s : String) : String;
function DCUExculdeParamNames(s : String) : String;
var BPLPEHeader : TPEHeader;
Glob_B5, Glob_B6, Glob_B7, Glob_B10 : Cardinal;
bMakeCRC : Boolean;
FirstByteSet : Set of Byte;
FirstCodeRVA : Cardinal;
implementation
Uses DeDeDisASM, DisASM, HexTools, DeDeBPL, VCLUnZip, SysUtils, Dialogs, crc32, DeDeRES;
var DASM : TDisAsm;
function InCodeSegment(s : String) : Boolean; overload;
var rva,i : dword;
DELTA_PHYS : DWORD;
begin
Result:=False;
If Length(s)<>8 Then Exit;
For i:=1 to length(s) do if not (s[i] in ['0'..'9', 'A'..'F']) then Exit;
rva:=Hex2DWORD(s);
DELTA_PHYS:= BPLPEHeader.IMAGE_BASE
+BPLPEHeader.Objects[1].RVA
-BPLPEHeader.Objects[1].PHYSICAL_OFFSET;
Result:=((RVA-DELTA_PHYS)>=BPLPEHeader.Objects[1].PHYSICAL_OFFSET)
and ((RVA-DELTA_PHYS)<=BPLPEHeader.Objects[1].PHYSICAL_OFFSET+BPLPEHeader.Objects[1].PHYSICAL_SIZE)
end;
function InCodeSegment(rva : dword) : Boolean; overload;
var DELTA_PHYS : DWORD;
begin
//Result:=False;
DELTA_PHYS:= BPLPEHeader.IMAGE_BASE
+BPLPEHeader.Objects[1].RVA
-BPLPEHeader.Objects[1].PHYSICAL_OFFSET;
Result:=((RVA-DELTA_PHYS)>=BPLPEHeader.Objects[1].PHYSICAL_OFFSET)
and ((RVA-DELTA_PHYS)<=BPLPEHeader.Objects[1].PHYSICAL_OFFSET+BPLPEHeader.Objects[1].PHYSICAL_SIZE)
end;
function Power(x,y : DWORD) : DWORD;
var i : Integer;
begin
result:=1;
for i:=1 to y do result:=result*x;
end;
// CRC of bytes aof called procedures
Procedure MakeCallCRC(var CRC : DWORD; buff : TSymBuffer; ipos : Integer; RVA : DWORD);
var dwOffset : DWORD;
Offs : LongInt;
i : Integer;
pbuf : TSymBuffer;
begin
dwOffset:=0;
if iPos>_PatternSize-4 then exit;
for i:=0 to 3 do dwOffset:=dwOffset+buff[iPos+i]*Power(256,i);
// This offset is relative and should be corrected
dwOffset:=dwOffset+iPos+5;
Offs:=PEHeader.Objects[1].PHYSICAL_OFFSET -PEHeader.Objects[1].RVA -PEHeader.IMAGE_BASE+RVA;
if buff[iPos+3]=$FF then Offs:=Offs+(dwOffset-$FFFFFFFF)
else Offs:=Offs+dwOffset;
if Offs>DeDeClasses.PEFile.PEStream.Size-_PatternSize then exit;
if Offs<0 then exit;
DeDeClasses.PEFile.PEStream.BeginSearch;
FillChar(pbuf,sizeof(pbuf),0);
Try
DeDeClasses.PEFile.PEStream.Seek(Offs,soFromBeginning);
DeDeClasses.PEFile.PEStream.ReadBuffer(pbuf[1],_PatternSize);
// The function that is called is export;
if (pbuf[1]=$FF) and (pbuf[2]=$25) then exit;
UnlinkCalls(pbuf,1);
crc32.crc32val:=CRC;
crc32.updatecrc(pbuf,_PatternSize);
CRC:=crc32.crc32val;
Finally
DeDeClasses.PEFile.PEStream.EndSearch;
End;
End;
Function UnlinkCalls(Var buff : TSymBuffer; Level : byte = 0; RVA : DWORD = 0) : Boolean;
var s{,ins} : String;
j,k,i{,ps} : Integer;
// w : Word;
dw : DWORD;
CRC : DWORD;
Begin
j:=1;
if Level=0 then CRC:=0;
Repeat
s:=DASM.GetInstruction(@buff[j],k);
if k=5 then
begin
// 5 byte instructions
// E8XXXXXXXX - Call address (same segment)
// 9AXXXXXXXX - Call address (other segment)
// 68XXXXXXXX - Push address (same segment)
// B8-BF - Mov reg32, value **! these ones are neseccary !!!
///A0-A3 - eax,al moves
// E9xxxxxxxx - Long jump
////////////////////////////////////////////////////
//// FOR NEW DSF ENGINE - CRC CHECK INCLUDED
////////////////////////////////////////////////////
if (Level=0) and (bMakeCRC) then
if (buff[j] in [$E8,$9A])
then MakeCallCRC(CRC, buff, j+1, RVA);
////////////////////////////////////////////////////
if buff[j] in [$E8,$E9,$9A,$A0..$A3,$A9]
then begin
for i:=1 to 4 do buff[j+i]:=0;
Inc(Glob_B5);
end;
/////////////////////////////////////////////////////////
// Unlink only if the value is > IMAGE_BASE+BASE_OF_CODE
// DO IT ALWAYS !!! (Many Idents build from DCU not found)
/////////////////////////////////////////////////////////
if buff[j] in [$68,$B8..$BF]
then begin
//dw:=buff[j+1]+buff[j+2]*256+buff[j+3]*256*256+buff[j+4]*256*256*256;
//if dw>=FirstCodeRVA then
// begin
for i:=1 to 4 do buff[j+i]:=0;
Inc(Glob_B5);
// end;
end;
end;
if k=6 then
begin
// 6 byte instructions
//
// FF05xxxxxxxx - Inc dword ptr [offset]
// FF0Dxxxxxxxx - Dec dword ptr [offset]
// FF15xxxxxxxx - Call dword ptr [offset]
// FF1Dxxxxxxxx - Call [offset]
// FF25xxxxxxxx - Jmp dword ptr [offset]
// FF2Dxxxxxxxx - Jmp [offset]
// FF35xxxxxxxx - Push dword ptr [offset]
//
// 86 - xchg [offset], reg16
// 8A - mov reg16, byte ptr [offset]
// 8B - mov reg32, dword ptr [offset]
// 8C - mov word ptr [offset], segreg
// 8D - lea reg32, [offset]
// 8E - mov segreg, word prt [offset]
//
// C5 - lds reg32, [offset]
//
// D8..DF, second byte in [05,0D..35,3D] -> FPU instructions
// that works with relative offsets
////////////////////////////////////////////////////
//// FOR NEW DSF ENGINE - CRC CHECK INCLUDED
////////////////////////////////////////////////////
//if Level=0 then
// if (buff[j]=$FF) and (buff[j+1] in [$15,$1D])
// then MakeCallCRC(CRC, buff, j+2);
////////////////////////////////////////////////////
if ((buff[j] in [$FF]) and (buff[j+1] in [$05,$0D,$15,$1D,$25,$2D,$35]))
or ((buff[j] in [$84..$8F, $C4..$C5]) and (buff[j+1] in [$05,$0D,$15,$1D,$25,$2D,$35,$3D,$80..$83,$85..$8B,$8D..$93,$95..$9B,$9D..$A3,$A5..$AB,$AD..$B3,$B5..$BB,$BD..$BF]))
or ((buff[j]=$0F) and (buff[j+1] in [$84,$85])
or ((buff[j] in [$D8..$DF]) and (buff[j+1] in [$05,$0D,$15,$1D,$25,$2D,$35,$3D]))
or (buff[j]=$C7))
then begin
for i:=2 to 5 do buff[j+i]:=0;
Inc(Glob_B6);
end;
end;
if k=7 then
begin
// 7 byte instructions
// 80 ..83 - add, or, adc, sbb, and, sub, xor, cmp
// ?? ptr [offset], imidiate_??_data
/// FF0485xxxxxxxx inc dword ptr [offset+eax*4]
/// FF0D85xxxxxxxx dec dword ptr [offset+eax*4]
/// FF1485xxxxxxxx call dword ptr [offset+eax*4]
/// FF1C85xxxxxxxx call [$offset+eax*4]
/// FF2485xxxxxxxx jmp dword ptr [offset+eax*4]
/// FF2C85xxxxxxxx jmp [offset+eax*4]
/// FF3485xxxxxxxx push dword ptr [offset+eax*4]
/// C605xxxxxxxxYY mov byte ptr [$48BB0D], $YY
/// 8B0485xxxxxxxx
//
// FPU Stuff
// D8..DF, 0C..3C|04..34, 05..F5|0D..FD
if ( (buff[j+0] in [$C6, $80..$83]) and (buff[j+1] in [$05,$0D,$15,$1D,$25,$2D,$35,$3D,$85,$8D,$95,$9D,$A5,$AD,$B5,$BD]))
or ((buff[j+0] in [$D8..$DF,$8B,$FF]) and (buff[j+1] in [$04,$0C,$14,$1C,$24,$2C,$34]) and (buff[j+2] in [$05,$0D,$15,$1D,$25,$2D,$35,$3D,$85,$8D,$95,$9D,$A5,$AD,$B5,$BD,$C5,$CD,$E5,$ED,$F5,$FD])
or ((buff[j+0] in [$C7]) and (buff[j+1] in [$40..$7F])))
then begin
if (buff[j+0] in [$C7])
then for i:=3 to 6 do buff[j+i]:=0
else for i:=2 to 5 do buff[j+i]:=0;
Inc(Glob_B7);
end;
end;
if k=10 then
begin
// 10 byte instructions
//
// 81 - add, or, adc, sbb, and, sub, xor, cmp
// dword ptr [offset], imidiate_dword_data
//
// C705 - mov dword ptr [offset], imidiate_dword_data
//
// 69 [05,0D..35,3D] -> imul reg, [offset], imm_data
if ( (buff[j+0] in [$81])
and (buff[j+1] in [$05,$0D,$15,$1D,$25,$2D,$35,$3D,
$85,$8D,$95,$9D,$A5,$AD,$B5,$BD]))
or ((buff[j]=$C7) {and (buff[j+1]=$05)})
or ((buff[j]=$69) and (buff[j+1] in [$05,$0D,$15,$1D,$25,$2D,$35,$3D]))
then begin
for i:=2 to 5 do buff[j+i]:=0;
Inc(Glob_B10);
end;
end;
j:=j+k;
Until (j>=_PatternSize) or (s='ret');
Result:=j>=3;
For i:=j to _PatternSize do
buff[i]:=0;
////////////////////////////////////////////////////
//// FOR NEW DSF ENGINE - CRC CHECK INCLUDED
////////////////////////////////////////////////////
if CRC<>0 then
begin
buff[_PatternSize-0]:=CRC;
buff[_PatternSize-1]:=CRC shr 8;
buff[_PatternSize-2]:=CRC shr 16;
buff[_PatternSize-3]:=CRC shr 24;
end;
End;
{ TDeDeSymbol }
constructor TDeDeSymbol.Create;
begin
Inherited Create;
Sym:=TMemoryStream.Create;
Str:=TMemoryStream.Create;
end;
destructor TDeDeSymbol.Destroy;
begin
Sym.Free;
Str.Free;
Inherited Destroy;
end;
function TDeDeSymbol.LoadSymbol(AsFileName: String): Boolean;
var FS : TMemoryStream;
s : String;
UnZip : TVCLUnZip;
begin
Result:=False;
Sym.Clear;
Str.Clear;
Try
FS:=TMemoryStream.Create;
UnZip:=TVCLUnZip.Create(nil);
Try
UnZip.ZipName:=AsFileName;
UnZip.UnZipToStream(FS,ExtractFileName(AsFileName));
FS.Seek(0,soFromBeginning);
Finally
UnZip.Free;
End;
Try
// Read Magic
SetLength(s,4);
FS.ReadBuffer(s[1],4);
If s<>'DSF!' Then Exit;
// Read Flags
FS.ReadBuffer(Mode,1);
// Read Record Count
FS.ReadBuffer(Count,2);
Finally
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -