📄 dededisasm.pas
字号:
t_e_str : String;
Begin
// sTRY_1e = '64FF30648920';// push dword ptr fs:[eax]; mov fs:[eax], esp
// sTRY_2e = '64FF32648922';// push dword ptr fs:[edx]; mov fs:[edx], esp
// sTRY_3e = '64FF31648921';// push dword ptr fs:[ecx]; mov fs:[ecx], esp
bk:=PEStream.Position;
Try
ph:=RVAConverter.GetPhys(RVA);
PEStream.Seek(ph,soFromBeginning);
SetLength(t_e_str,6);
PEStream.ReadBuffer(t_e_str[1],6);
Result:= (t_e_str=#$64#$FF#$30#$64#$89#$20)
or (t_e_str=#$64#$FF#$32#$64#$89#$22)
or (t_e_str=#$64#$FF#$31#$64#$89#$21);
Finally
PEStream.Seek(bk,soFromBeginning);
End;
End;
// Returns true if the current instruction is
// the beginning of a EXCEPT-END block
Function IsExceptBlock : Boolean;
var bk : DWORD;
ph : DWORD;
b : Byte;
t_e_str : String;
Begin
bk:=PEStream.Position;
Try
ph:=RVAConverter.GetPhys(RVA);
PEStream.Seek(ph+3,soFromBeginning);
SetLength(t_e_str,1);
PEStream.ReadBuffer(t_e_str[1],1);
Result:=t_e_str[1]=#$EB;
If Result Then Begin
PEStream.ReadBuffer(b,1);
LastPush:=rva+b+5;
End;
Finally
PEStream.Seek(bk,soFromBeginning);
End;
End;
// Returns true if the current instruction is
// the beginning of a FINALLY-END block
Function IsFinallyBlock : Boolean;
var bk : DWORD;
ph,dw : DWORD;
t_e_str : String;
Begin
bk:=PEStream.Position;
Try
ph:=RVAConverter.GetPhys(RVA);
PEStream.Seek(ph+3,soFromBeginning);
SetLength(t_e_str,1);
PEStream.ReadBuffer(t_e_str[1],1);
Result:=t_e_str[1]=#$68;
If Result Then Begin
PEStream.ReadBuffer(dw,4);
LastPush:=dw;
End;
Finally
PEStream.Seek(bk,soFromBeginning);
End;
End;
// If the current RVA is the END rva of a
// try-except or try-finally block then
// the reference is attached
function ReachedEND : String;
var i : Integer;
Begin
Result:='';
For i:=ENDPtrList.Count-1 DownTo 0 Do
If StrToInt64(ENDPtrList[i])=rva
Then Begin
ENDPtrList.Delete(i);
Result:=#13#10+sREF_TEXT_END+#13#10+'|'#13#10;
End;
End;
// If the current RVA is the EXCEPT rva of a
// try-except block then the reference is attached
Function ReachedExcept : String;
var i : Integer;
Begin
Result:='';
For i:=SEHPtrList.Count-1 DownTo 0 Do
If StrToInt(SEHPtrList[i])=rva
Then Begin
SEHPtrList.Delete(i);
Result:=#13#10+sREF_TEXT_EXCEPT+#13#10+'|'#13#10;
End;
End;
// Here different references are find
// and comments are glued to the code
// ss is the ASM line
function ReplaseReferences(var ss : String) : String;
Var ins1,dta, sof, ofs : String;
i,ps : Integer;
idx : ShortInt;
dwdta,bk : Cardinal;
Begin
Result:='';
// Finds the firts space in the string
i:=Pos(#32,ss);
// Gets the instruction
ins1:=Copy(ss,1,i-1);
// Gets the operands
dta:=Copy(ss,i+1,Length(ss)-i);
// Removes spaces at the beginning and at the and
TruncAll(dta);
// If not operands then nothing to handle
If dta='' Then Exit;
///////////////////////////////////////////////
//// try-finally and try-except references ////
///////////////////////////////////////////////
// Put END if needed
If ENDPtrList.Count<>0 Then
Result:=ReachedEND;
// Put EXCEPT if needed
If SEHPtrList.Count<>0
Then Result:=Result+ReachedExcept;
If bCommentNext Then
Begin
// the instruction after the next push should be marked as FINALY
Result:=Result+#13#10+sREF_TEXT_FINALLY+#13#10+'|'#13#10;
bCommentNext:=False;
End;
// saves last push - to be proceeded if try is detected
If (ins1='push') and (Copy(dta,1,1)='$') then LastPush:=HEX2DWORD(Copy(dta,2,Length(dta)-1));
// Check For TRY
bTryBlockFound:=False;
If (ss='push dword ptr fs:[eax]')
or (ss='push dword ptr fs:[ecx]')
or (ss='push dword ptr fs:[edx]')
Then Begin
// Try-Exept-Finally Detected
If (IsTryExceptBlock) Then
Begin
SEHPtrList.Add(IntToStr(LastPush));
Result:=#13#10+sREF_TEXT_TRY+#13#10+'|'#13#10;
bTryBlockFound:=True;
End;
End;
// Check For EXCEPT or FINALLY
If (ss='mov fs:[eax], edx')
Then Begin
// Try-Exept-Finally Detected
If (IsExceptBlock) Then
Begin
// pushed the END offset
ENDPtrList.Add(IntToStr(LastPush));
End;
If (IsFinallyBlock) Then
Begin
// removes the try pushed offset
If SEHPtrList.Count<>0 Then SEHPtrList.Delete(SEHPtrList.Count-1);
// pushed the END offset
ENDPtrList.Add(IntToStr(LastPush));
// one ret should be skiped
Inc(bTryExcept);
// next instruction should be commented with FINALLY
bCommentNext:=True;
End;
End;
///////////////////////////////////////////////
///////////// Control References //////////////
///////////////////////////////////////////////
//
// normaly they are : mov eax, [eax+$xxxx]
// or : mov eax, [ebx+$xxxx]
// or : mov eax, [esi+$xxxx]
// or : mov edx, [eax+$xxxx]
//
// $xxxx is the control ID, specified in the ClassInfo block
//
{ ps:=Pos(', [eax+$',dta);
if ps=0 then ps:=Pos(', [ebx+$',dta);
if ps=0 then ps:=Pos(', [esi+$',dta);
if ps=0 then ps:=Pos(', [edx+$',dta);}
ps:=Pos('[eax+$',dta);
if ps=0 then ps:=Pos('[ebx+$',dta);
if ps=0 then ps:=Pos('[esi+$',dta);
if ps=0 then ps:=Pos('[edx+$',dta);
If (ps<>0) and ((ins1='mov') or (ins1='lea') or (ins1='cmp')) Then
Begin
Dec(ps,2); //Correction for ', '
sof:=ControlRef(Copy(dta,ps+8,4),Copy(dta,ps+3,3),Copy(dta,ps-3,3));
If sof<>'' Then
Begin
Result:=Result+sof;
Exit;
End;
End;
///////////////////////////////////////////////
///////////// String References ///////////////
///////////////////////////////////////////////
//
// if a 'push offset' or 'mov register, offset'
// and this offset is in the CODE section it
// can contain a string. Check this
//
If (ins1='push') or (ins1='mov') Then
Begin
ofs:=OffsetMightBeString(ins1,dta);
If ofs<>''
Then Begin
bk:=PEStream.Position;
Try
If not bTryBlockFound Then
begin
sof:=GetStringReference(ofs);
If sof<>'' Then
Result:=Result+#13#10+sREF_TEXT_REF_STRING+' '''+sof+''''#13#10+'|'#13#10;
end;
Finally
PEStream.Seek(bk,soFromBeginning);
End;
Exit;
End
Else Begin
// It could be mov eax, dword ptr [$offset]
// and this can be a handle to a form or also
// it can be a Constant Reference
// this can be imroved in future
End;
End;
///////////////////////////////////////////////
////////////// Call References ////////////////
///////////////////////////////////////////////
//
// First of all it the instruction is a relative
// jump or call then the real RVA should be shown !
//
If OffsetShouldCorrect(ins1) Then
Begin
Case dta[1] of
'-' : idx:=-1;
'+' : idx:=1
else Exit;
End;
sof:=Copy(dta,3,Length(dta)-2);
dwdta:=idx*HEX2DWORD(sof);
dwdta:=dwdta+rva+sz;
while Length(ins1)<8 do ins1:=ins1+' ';
ss:=ins1+DWORD2HEX(dwdta);
// This finds all the call references
if ins1='call ' then
Result:=RefCall(ss,dwdta);
exit;
End;
End;
// procedure DisassembleProc(NameP,S : String; var DasmList : TStringList; bNotClearText : Boolean = True; Custom : Boolean = False);
//
// Description : Disaasembles procedure.
//
// DeDeDisAsm.PEStream, PEHeader, RVAConverter, DFMText,
// , ControlIDs, ControlNames, ClsDmp and SymbolList
// should be set before calling this procedure. Their meaning is
// the following:
//
// *) PEStream is the file, if not set exception will occure
// *) PEHeader is the PE header of the file, if not set exception will occure
// *) RVAConverter is used to convert RVAs to Physical offsets, if not set exception will occure
// *) DFMText is the text representation of the DFM resources of the current form.
// if not set control references will not have the class names of controls
// *) ControlIDs and ControlNames are the IDs and names of the controls in the form
// if not set no control references will be found
// *) ClsDmp is the TClassDumper object of the current class
// if not set no published/VIRT/USER proc references will be found
// *) SymbolList is a TList with loaded TDeDeSymbol objects
// if not set no calls to VCL and other BPLs will be found
//
// Parameter Description:
// NameP : Unit name
// S : Procedure Name
// DasmList : A TStringList that will contain the result
// of disassembling. This object should not be
// created before calling the DisassembleProc().
// If is created from the procedure itself. The
// calling procedure should free this object after
// assign the lines to another TStringList or after
// saving it to a file.
// bNotClearText : If Flase then NameP is the unit name and
// S is the rocedure name, that should exist in the
// ClsDmp object MethodList.
// If True then NameP is the unit name, ending with
// '.pas' and S is the full name of the procedure
// like in pascal implementation part. For example:
// NameP = Unit11.pas
// s = procedure TForm11.CaptionMaskMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer);
// (NOTE: this flag is used to differ normal disassembly from
// saving a Delphi project space. There is no special reason of
// having this parameter and DisassemblerProc() does the same
// things in the both cases. The default value is TRUE)
// Custom : If TRUE then the DisassembleProc will not seek for the
// proc RVA addres and will start to dissasebmle from the current
// position of the PEStream. If this parameter is not specified then
// the default value is FALSE
//
// EmulateOnly : If TRUE then ptocedure is only emulated to dwEmulateToOffset offset.
// This is used to initialize registes when disassembling subprocedures
//
// dwEmulateToOffset : The end offset (excluding it) to where the procedure should be
// emulated. If this offset is beyond the end of the procedure emulation
// ends with the end of the procedure. If it is zero then no emulation is
// done at all.
//
// Last Modified : 11.I.2001
//
procedure DisassembleProc(NameP,S : String; var DasmList : TStringList; bNotClearText : Boolean = True; Custom : Boolean = False; EmulateOnly : Boolean = False; dwEmulateToOffset : DWORD = 0);
var iStopIndex, i,k,locpos, InstrId : Integer;
ss : String;
DASM : TDisAsm;
pc,op,srf, locvar : String;
begin
// Creates The Result
DasmList:=TStringList.Create;
if not Custom then
if GlobBEmulation then
if not GlobCustomEmulInit
then InitNewEmulation('','','','');
rva:=0;
If Not Custom Then
Begin
// This retreives the RVA offsets of the first instruction
// and moves the steram pointer to this offset
If bNotClearText Then
Begin
i:=Pos('.',NameP);
NameP:=Copy(NameP,1,i-1);
End;
If bNotClearText Then
Begin
i:=Pos('.',S);
s:=Copy(s,i+1,Length(s)-i);
i:=Pos('(',s);
s:=Copy(s,1,i-1);
End;
rva:=ClsDmp.GetMethodRVA(s);
if GlobBEmulation then
if not GlobCustomEmulInit then
InitNewEmulation(ClsDmp.FsClassName,'','','');
ss:=DWORD2HEX(RVAConverter.GetPhys(rva));
PEStream.Seek(HEX2DWORD(ss),soFromBeginning);
End
// Else if bCustom=True, the Stream is set to this first
// instruction and need just to get its RVA address
Else rva:=RVAConverter.GetRVA(PEStream.Position);
If rva=0 then Exit;
ProcRva:=rva;
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
//////////// The Main Diassembly Loop /////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
// Creates the OPCODE_to_ASM disassembler object
DASM:=TDisAsm.Create;
// The number of the current instruction
InstrId:=0;
// Stop if this insruction number is reached.
iStopIndex:=-1;
Try
Try
// Clears SEH List (try_except and try_finally blocks)
SEHPtrList.Clear;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -