📄 dededisasm.pas
字号:
// Initialize the number of found TRY blocks to 0
// (this is used for the both try_finally and
// for try_except blocks)
bTryExcept:=0;
// Clears the list with END_try and END_fynally offsets
ENDPtrList.Clear;
// Initialize the last short jump otside the current RVA
// to 'not present'
LastJump:=0;
// Inititaliza the size of the last instruction in bytes to 0
sz:=0;
Repeat
Repeat
// Sets lenth in bytes of the largest instruction
SetLength(pc,17);
// Reads next byets
PEStream.ReadBuffer(pc[1],16);
// Disassembels them
ss:=DASM.GetInstruction(PChar(pc),sz);
Inc(InstrId);
// If the current instruction is a short jump ahead
// then sets the LastJump
If (ORD(pc[1]) in [$70..$7F,$EB]) and
(ORD(pc[2])<$7F) Then
if LastJump<rva+2+ORD(pc[2])
then LastJump:=rva+2+ORD(pc[2]);
// If the last short jump ahead is passed
// sets the last jump to zero
If LastJump<=rva Then LastJump:=0;
// Finds all kind of references and attches them before
// the disassembeld instruction
bControlRef:=False;
srf:=ReplaseReferences(ss);
// More references !!!
if (GlobBEmulation)
// if control reference is found then skip emulation
and (not bControlRef) then
begin
EmulateInstruction(pc,sz,ss,ss);
If bReference then
begin
if srf='' then srf:=#13#10;
///////////////////////////////////////////////////////
// srf:=srf+'* '+sReference+#13#10+'|'#13#10;
// '* ' was removed when made references texts standart
///////////////////////////////////////////////////////
srf:=srf+sReference+#13#10+'|'#13#10;
end;
end;
//Gets Local Var References
locpos:=Pos('[ebp-$',ss);
if locpos=0 then locpos:=Pos('[ebp+$FFFF',ss);
if locpos<>0 then
begin
locvar:=Copy(ss,locpos,locpos+10);
locpos:=Pos(']',locvar);
locvar:=Copy(locvar,1,locpos);
AddNewExpression(ProcRVA,locvar,'');
end;
// Gets the string representation of OPCODEs
op:='';
For k:=1 To sz Do op:=op+Byte2HEX(ORD(pc[k]));
While Length(op)<20 Do op:=op+' ';
// Adds the current instruction and references to the
// result StringList
if not EmulateOnly then
DasmList.Add(srf+DWord2HEX(rva)+' '+op+' '+ss);
// Calculates the RVA address of the next instruction
rva:=rva+sz;
// If it is emulation and end offset is reached then exit proc
if (EmulateOnly) and (rva>=dwEmulateToOffset) then exit;
// Moves the pointer in the stream at the beginning
// of the next instruction according to the last
// instruction size in bytes. 16 is the max length of
// an instruction
PEStream.Seek(sz-16,soFromCurrent);
// This is especially for the Delphi compiler
// This can be and of a procedure. This is
// used to find the end of the DPR code and
// in some other special cases
if (ss='add [eax], al') and (SEHPtrList.Count=0) then
break;
// This is the first instruction and it is jump to offset. Probably
// from import section. Stop Disassembly after.
If (ORD(pc[1])=$FF) and (ORD(pc[2])=$25) and (InstrId=1)
Then iStopIndex:=2;
// If we should stop then exit
if InstrId=iStopIndex then exit;
// Repeats disassembly until a 'RET' has been reached
Until copy(ss,1,3)='ret';
// Decreases the number of try blocks
Dec(bTryExcept);
// Adds an empty line to the result StringList
DasmList.Add('');
// Repeats until all try blocks has been closed
Until (SEHPtrList.Count=0) and (bTryExcept<0) and (LastJump=0);
Except
// On exception shows the error
On E:Exception Do
if not bErrorsAsFile then
MessageBox(0,PChar(
'Exception: '+E.Message+#13#10+
'Proc Name: '+NameP+'.'+s+#13#10+
'Last Instruction: '+DWord2HEX(rva)+' '+op+' '+ss+#13#10+
'Current Position: '+IntToHex(PEStream.Position,8)),
PChar(err_dasm_err),0)
else sDisAsmErrors:=sDisAsmErrors+#13#10+
'Exception: '+E.Message+#13#10+
'Proc Name: '+NameP+'.'+s+#13#10+
'Last Instruction: '+DWord2HEX(rva)+' '+op+' '+ss+#13#10+
'Current Position: '+IntToHex(PEStream.Position,8)+
#13#10;
End;
Finally
// Frees the TDASM object
DASM.Free;
// Restore Disassembly Options. They should be set before every call to DiassembleProc!!
DisassemblerOptions.Imports:=True;
DisassemblerOptions.EnglishStrings:=True;
DisassemblerOptions.NonEnglishStrings:=True;
End;
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
//////////// End Of The Main Diassembly Loop //////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
end;
function GetNextProcRVA(dwRVA : DWORD; var bFound : Boolean; bSkipBetweenCodeFillRecognition : Boolean = False) : DWORD;
var DASM : TDisAsm;
phys : DWORD;
pc,ss : String;
sz{,i} : LongInt;
begin
DASM:=TDisAsm.Create;
try
phys:=RVAConverter.GetPhys(dwRVA);
PEStream.Seek(phys,soFromBeginning);
rva:=dwRVA;
Result:=0;
if (phys<=0) then Exit;
if (phys>=PEStream.Size) then Exit;
SEHPtrList.Clear;
bTryExcept:=0;
ENDPtrList.Clear;
LastJump:=0;
sz:=0;
Repeat
Repeat
SetLength(pc,17);
PEStream.ReadBuffer(pc[1],16);
ss:=DASM.GetInstruction(PChar(pc),sz);
If (ORD(pc[1]) in [$70..$7F,$EB]) and
(ORD(pc[2])<$7F) Then
if LastJump<rva+2+ORD(pc[2])
then LastJump:=rva+2+ORD(pc[2]);
If LastJump<=rva Then LastJump:=0;
If ENDPtrList.Count<>0 Then ReachedEND;
If SEHPtrList.Count<>0 Then ReachedExcept;
If ORD(pc[1])=$68 then LastPush:=ORD(pc[2])+ORD(pc[3])*256+(ORD(pc[4])+ORD(pc[5])*256)*256*256;
bTryBlockFound:=False;
If Copy(pc,1,6)=#$64#$FF#$30#$64#$89#$20 Then
Begin
SEHPtrList.Add(IntToStr(LastPush));
bTryBlockFound:=True;
End;
If Copy(pc,1,3)=#$64#$89#$10
Then Begin
If pc[4]=#$EB Then ENDPtrList.Add(IntToStr(LastPush));
If pc[4]=#$68 Then
Begin
If SEHPtrList.Count<>0 Then SEHPtrList.Delete(SEHPtrList.Count-1);
ENDPtrList.Add(IntToStr(LastPush));
Inc(bTryExcept);
End;
End;
rva:=rva+sz;
PEStream.Seek(sz-16,soFromCurrent);
if (ORD(pc[1])=0) and (ORD(pc[2])=0) then break;
Until Copy(ss,1,3)='ret';
Dec(bTryExcept);
Until (SEHPtrList.Count=0) and (bTryExcept<0) and (LastJump=0);
Result:=rva;
If bSkipBetweenCodeFillRecognition then Exit;
//Result:=0;
// separators
// 1 byte : 90 nop
// 2 byte : 8BC0 mov eax, eax
// 3 byte : 8D4000 lea eax, [eax+00]
// end_of_procs = 0000, 00FFFFFF
bFound:=True;
If (pc[sz+1]=#$90) then Inc(rva,1) else
If (pc[sz+1]=#$8B) and (pc[sz+2]=#$C0) then Inc(rva,2) else
If (pc[sz+1]=#$8D) and (pc[sz+2]=#$40) and (pc[sz+3]=#$00) then Inc(rva,3) else
If (pc[sz+1] in [#$55,#$83]) then asm NOP end else
begin
//bFound:=False;
//procs starting with 00 or FF are not procs
If (pc[sz+1]=#$FF) then bFound:=False;
if (pc[sz+1]=#$00) and (pc[sz+2] in [#$00,#$FF]) then bFound:=False;
//procs finishing with 0000 are not procs
if (ORD(pc[1])=0) and (ORD(pc[2])=0) then bFound:=False;
if not bFound then
begin
repeat
PEStream.ReadBuffer(pc[1],1);
Inc(rva);
until pc[1] in [#$55,#$83];
bFound:=pc[1] in [#$55,#$83]
end;
end;
Result:=rva;
Finally
DASM.Free;
End;
end;
//////////////////////////////////////////////////////
// Seeks InitUnits routine from system.pas
// and returns its phisical offset
/////////////////////////////////////////////////////
Function GetInitUnitsProcRVA : DWORD;
var l, iiDW : DWORD;
buff : TSymBuffer;
begin
iiDW:=0;
PEFile.PEStream.BeginSearch;
Try
For l:=0 to PEFile.PEStream.Size-sizeOf(buff)-1 Do
begin
PEFile.PEStream.Seek(l,soFromBeginning);
PEFile.PEStream.ReadBuffer(buff,sizeof(buff));
If DelphiVersion='D2' then
begin
If (buff[1]=$55) and (buff[12]=$85) and (buff[13]=$C0) and (buff[14]=$74) and (buff[15]=$4B)
then begin
UnlinkCalls(buff);
if CompareMem(@buff[1], @D2_InitUnitsIdent[1], 49) then
begin
// InitInstance Procedure Found
iiDW:=l;
break;
end;
end;
end; {Delphi5 Recognition}
If DelphiVersion='D3' then
begin
If (buff[1]=$55) and (buff[12]=$85) and (buff[13]=$C0) and (buff[14]=$74) and (buff[15]=$4B)
then begin
UnlinkCalls(buff);
if CompareMem(@buff[1], @D3_InitUnitsIdent[1], 49) then
begin
// InitInstance Procedure Found
iiDW:=l;
break;
end;
end;
end; {Delphi5 Recognition}
If DelphiVersion='D4' then
begin
If (buff[1]=$55) and (buff[12]=$85) and (buff[13]=$C0) and (buff[14]=$74) and (buff[15]=$4B)
then begin
UnlinkCalls(buff);
if CompareMem(@buff[1], @D4_InitUnitsIdent[1], 49) then
begin
// InitInstance Procedure Found
iiDW:=l;
break;
end;
end;
end; {Delphi4 Recognition}
If DelphiVersion='D5' then
begin
If (buff[1]=$55) and (buff[12]=$85) and (buff[13]=$C0) and (buff[14]=$74) and (buff[15]=$4B)
then begin
UnlinkCalls(buff);
if CompareMem(@buff[1], @D4_InitUnitsIdent[1], 49) then
begin
// InitInstance Procedure Found
iiDW:=l;
break;
end;
end;
end; {Delphi5 Recognition}
If (DelphiVersion='D6') or (DelphiVersion='D6 CLX') then
begin
If (buff[1]=$55) and (buff[12]=$85) and (buff[13]=$C0) and (buff[14]=$74) and (buff[15]=$4B)
then begin
UnlinkCalls(buff);
if CompareMem(@buff[1], @D6_InitUnitsIdent[1], 49) then
begin
// InitInstance Procedure Found
iiDW:=l;
break;
end;
end;
end; {Delphi6 Recognition}
If DelphiVersion='DConsole' then
begin
If (buff[1]=$55) and (buff[12]=$85) and (buff[13]=$C0) and (buff[14]=$74) and (buff[15]=$4B)
then begin
UnlinkCalls(buff);
if CompareMem(@buff[1], @D6_InitUnitsIdent[1], 49) then
begin
// InitInstance Procedure Found
iiDW:=l;
break;
end;
end;
end; {Delphi6 Recognition}
end;
Finally
PEFile.PEStream.EndSearch;
End;
Result:=iiDW;
End;
initialization
UnitList:=TStringList.Create;
SEHPtrList:=TStringList.Create;
ENDPtrList:=TStringList.Create;
DFMText:=TStringList.Create;
ControlNames:=TStringList.Create;
ControlIds:=TStringList.Create;
DisassemblerOptions.Imports:=True;
DisassemblerOptions.EnglishStrings:=True;
DisassemblerOptions.NonEnglishStrings:=True;
finalization
UnitList.Free;
SEHPtrList.Free;
ENDPtrList.Free;
DFMText.Free;
ControlNames.Free;
ControlIDs.Free;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -