📄 dededcu.pas
字号:
unit DeDeDCU;
interface
Uses DeDeClasses, Classes;
Type DWORD = LongWord;
Type TDCUDecoder = Class (TObject)
protected
DCUOffset : LongInt;
FdwImageBase, FdwCodeRVA, FdwCodeSize : DWORD;
Function ReadPascalStringBack : String;
Function ReadOffsetBack : DWORD;
Function ReadWordBack : Word;
Function ReadByteBack : Byte;
Function OffsetInCodeSegment(Offset : DWORD) : Boolean;
public
PEStream : TPEStream;
Constructor Create;
Destructor Destroy; override;
procedure SetPEData(ImageBase,CodeRVA,CodeSize : DWORD);
function Dump(AsOffset : String; OpCodeList, ControlList : TStringList) : String;
End;
implementation
Uses HEXTools, DeDeConstants, SysUtils;
{ TDCUDecoder }
constructor TDCUDecoder.Create;
begin
Inherited Create;
end;
destructor TDCUDecoder.Destroy;
begin
Inherited Destroy;
end;
// Result if name of the form corresponding to the unit
function TDCUDecoder.Dump(AsOffset: String;
OpCodeList, ControlList: TStringList): String;
var s : String;
sFormName : String;
Pat : TPaternQuery;
bFound, bMidHeaderFound : Boolean;
iOffset,i,j : LongInt;
iEventCount : Integer;
wReadCount : WORD;
begin
Result:='';
If PEStream=nil Then Exit;
If OpCodeList=nil Then Exit;
If ControlList=nil Then Exit;
// ShowMessage('DCUDump Eneter');
With PEStream Do
Begin
BeginSearch;
//Moves to DCU Offset Footer
Seek(HEX2DWORD(AsOffset),soFromBeginning);
Try
// Finds End of FormClassName
Seek(-iDCU_CONST1-1,soFromCurrent);
// Reads ClassName
s:=ReadPascalStringBack;
sFormName:=s;
// Finds Where RVA List Ends. It Ends with ClassName String
Pat:=TPaternQuery.Create;
Try
// Set ClassName String
Pat.SetString(s);
// Backuops current offset
iOffset:=Position;
i:=iOffset;
Repeat
//Moves 1 byte back
Seek(i-1,soFromBeginning);
//Looks if there is ClassName string there
bFound:=PatternMach(Pat);
//Decreses CurrentPosition
Dec(i);
Until (bFound) or (Position-iOffset>iDCU_CONST2);
If Not bFound Then Raise Exception.Create('DCU Engine Error L20');
//Pattern does not contain length-byte, so we must sub. it
Seek(i-1,soFromBeginning);
//Skips Additional Data If There Are Any
i:=0;
bMidHeaderFound:=False;
j:=ReadOffsetBack;
While OffsetInCodeSegment(j) Do
Begin
bMidHeaderFound:=True;
Inc(i);
j:=ReadOffsetBack;
End;
Seek(4,soFromCurrent);
If bMidHeaderFound Then
Begin
For j:=1 To i Do ReadWordBack;
j:=ReadWordBack;
If j<>i Then
Begin
//Raise Exception.Create('DCU Engine Error L21. Class:"'+sFormName+'". Phisical Offset:'+DWORD2HEX(Position));
// ShowMessage('Mid Header Skipped Succesfully In: '+sFormName+' DCU !');
OpCodeList.Clear;
Exit;
End;
End;
//Sets DCU Offset
DCUOffset:=Position;
Finally
Pat.Free;
End;
// Puts Header in EventOffsetDump StringList
OpCodeList.Add('{'+sFormName);
OpCodeList.Add('');
// Initialize Event Read (No Events have been read yet)
iEventCount:=0;
Repeat
//Reads Word Back
wReadCount:=ReadWordBack;
//Checks to see if this equals the event count read so far
IF wReadCount=iEventCount
// If so, then break. All event handlers have been read
Then Break;
// Else return forward to prepare for reading
Seek(2,soFromCurrent);
// Reads EventName, EventOffset and EventHint
s:=ReadPascalStringBack;
i:=ReadOffsetBack;
j:=ReadWordBack;
// Check To see if this is a EventHandler Data
// Of no events present. If last so i must not be
// an offset in the code segment
If Not OffsetInCodeSegment(i) Then Break;
//Puts Dumped Record in the stringlist
s:=sFormName+'.'+s;
While Length(s)<40 Do s:=s+' ';
OpCodeList.Add(s+DWORD2HEX(i)+' hint:'+WORD2HEX(j));
//Increaces Events Read so far
Inc(iEventCount);
Until False;
///////////////////////////////////////////////////////
/// Controls IDs can be readed here
///////////////////////////////////////////////////////
ControlList.Clear;
// Moves 4 bytes forward
Seek(4,soFromCurrent);
// control name is stored in s, so read only IDs
j:=ReadWordBack;
i:=ReadOffsetBack;
ControlList.Add(Format('%s,%s',[s,i]));
Repeat
// Reads ControlName, Number and ControlID
s:=ReadPascalStringBack;
j:=ReadWordBack;
i:=ReadOffsetBack;
ControlList.Add(Format('%s,%s',[s,i]));
Until j=0;
ShowMessage(ControlList.Text);
///////////////////////////////////////////////////////
/// End of Control IDs data
///////////////////////////////////////////////////////
//Puts EventOffsetDump StringList Footer
OpCodeList.Add('}');
//ShowMessage(OpCodeList.Text);
//Result is the form name
Result:=sFormName;
Finally
EndSearch;
End;
End;
end;
function TDCUDecoder.OffsetInCodeSegment(Offset: DWORD): Boolean;
begin
Result:= (Offset>FdwImageBase+FdwCodeRVA)
and (Offset<FdwImageBase+FdwCodeRVA+FdwCodeSize);
end;
function TDCUDecoder.ReadByteBack: Byte;
Var b : Byte;
begin
PEStream.Seek(-1,soFromCurrent);
PEStream.ReadBuffer(b,1);
PEStream.Seek(-1,soFromCurrent);
Result:=b;
end;
function TDCUDecoder.ReadOffsetBack: DWORD;
Var b1,b2,b3,b4 : Byte;
begin
PEStream.Seek(-4,soFromCurrent);
PEStream.ReadBuffer(b1,1);
PEStream.ReadBuffer(b2,1);
PEStream.ReadBuffer(b3,1);
PEStream.ReadBuffer(b4,1);
PEStream.Seek(-4,soFromCurrent);
Result:=b1+b2*256+(b3+b4*256)*256*256;
end;
function TDCUDecoder.ReadPascalStringBack: String;
Var s : String;
b : Byte;
begin
s:='';
b:=ReadByteBack;
While b>32 Do
Begin
s:=CHR(b)+s;
b:=ReadByteBack;
End;
If b<>Length(s) Then
s:=Copy(s,2,Length(s)-1);
//Raise Exception.Create('DCU Dump Engine Error L10!');
Result:=s;
end;
function TDCUDecoder.ReadWordBack: Word;
Var b1,b2 : Byte;
begin
PEStream.Seek(-2,soFromCurrent);
PEStream.ReadBuffer(b1,1);
PEStream.ReadBuffer(b2,1);
PEStream.Seek(-2,soFromCurrent);
Result:=b1+b2*256;
end;
procedure TDCUDecoder.SetPEData(ImageBase,CodeRVA,CodeSize : DWORD);
begin
FdwImageBase:=ImageBase;
FdwCodeRVA:=CodeRVA;
FdwCodeSize:=CodeSize;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -