Skip to content

Commit

Permalink
Add some suppot for Themida v3, remove a couple MSVC-isms
Browse files Browse the repository at this point in the history
  • Loading branch information
Hendi48 committed Mar 8, 2022
1 parent 84a5339 commit 5c70453
Show file tree
Hide file tree
Showing 9 changed files with 593 additions and 245 deletions.
649 changes: 412 additions & 237 deletions Debugger.pas

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion Magicmida.dpr
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ uses
Dumper in 'Dumper.pas',
PEInfo in 'PEInfo.pas',
Patcher in 'Patcher.pas',
BeaEngineDelphi32 in 'BeaEngineDelphi32.pas';
BeaEngineDelphi32 in 'BeaEngineDelphi32.pas',
Tracer in 'Tracer.pas';

{$R *.res}

Expand Down
1 change: 1 addition & 0 deletions Magicmida.dproj
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
<DCCReference Include="PEInfo.pas"/>
<DCCReference Include="Patcher.pas"/>
<DCCReference Include="BeaEngineDelphi32.pas"/>
<DCCReference Include="Tracer.pas"/>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ Functions:
* Unpack: Unpacks the binary you select. The unpacked binary will be saved with an `U` suffix.
* MakeDataSects: Restores .rdata/.data sections. Only works on very specific targets.
* Dump process: Allows you to enter the PID of a running process whose .text section will be dumped (overwritten) into an already unpacked file. This is useful after using Oreans Unvirtualizer in OllyDbg. Only works properly if MakeDataSects was done before.
* Shrink: Deletes all sections that are no longer needed (if you unvirtualized or if your binary does not use virtualization).
* Shrink: Deletes all sections that are no longer needed (if you unvirtualized or if your binary does not use virtualization). Warning: This will break your binary for non-MSVC compilers.

Note: The tool focuses on cleanness of the resulting binaries. Things such as VM anti-dump are explicitly *not* fixed.
Note: The tool focuses on cleanness of the resulting binaries. Things such as VM anti-dump are explicitly *not* fixed. If your target has a virtualized entrypoint, the resulting dump will be broken and won't run (except for MSVC6, which has special fixup code to restore the OEP).

Important: Never activate any compatibility mode options for Magicmida or for the target you're unpacking. It would very likely screw up the unpacking process due to shimming.

## Anti-anti-debugging

Newer versions of Themida detect hardware breakpoints. In order to deal with this, injecting ScyllaHide is supported. A suitable profile is shipped with Magicmida. You just need to download SycllaHide and put `HookLibraryx86.dll` and `InjectorCLIx86.exe` next to `Magicmida.exe`. Do not overwrite scylla_hide.ini unless you know what you're doing.
119 changes: 119 additions & 0 deletions Tracer.pas
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
unit Tracer;

interface

uses Windows, SysUtils, Utils;

type
TTracePredicate = function(const C: TContext): Boolean of object;

TTracer = class
private
FProcessID, FThreadID: Cardinal;
FThreadHandle: THandle;
FPredicate: TTracePredicate;
FCounter, FLimit: Cardinal;
FLimitReached: Boolean;
Log: TLogProc;

function OnSingleStep(const Ev: TDebugEvent): Cardinal;
public
constructor Create(AProcessID, AThreadID: Cardinal; AThreadHandle: THandle;
APredicate: TTracePredicate; ALog: TLogProc);

procedure Trace(AAddress: NativeUInt; ALimit: Cardinal);

property Counter: Cardinal read FCounter;
property LimitReached: Boolean read FLimitReached;
end;

implementation

{ TTracer }

constructor TTracer.Create(AProcessID, AThreadID: Cardinal; AThreadHandle: THandle;
APredicate: TTracePredicate; ALog: TLogProc);
begin
FProcessID := AProcessID;
FThreadID := AThreadID;
FThreadHandle := AThreadHandle;
FPredicate := APredicate;
Log := ALog;
end;

procedure TTracer.Trace(AAddress: NativeUInt; ALimit: Cardinal);
var
C: TContext;
Ev: TDebugEvent;
Status: Cardinal;
begin
FCounter := 0;
FLimit := ALimit;
FLimitReached := False;

C.ContextFlags := CONTEXT_CONTROL;
if not GetThreadContext(FThreadHandle, C) then
RaiseLastOSError;

C.Eip := AAddress;
C.EFlags := C.EFlags or $100; // Trap
if not SetThreadContext(FThreadHandle, C) then
RaiseLastOSError;

if not ContinueDebugEvent(FProcessID, FThreadID, DBG_CONTINUE) then
Exit;

Status := DBG_EXCEPTION_NOT_HANDLED;
while WaitForDebugEvent(Ev, INFINITE) do
begin
case Ev.dwDebugEventCode of
EXCEPTION_DEBUG_EVENT:
begin
if Ev.Exception.ExceptionRecord.ExceptionCode = EXCEPTION_SINGLE_STEP then
begin
Status := OnSingleStep(Ev);
if Status = DBG_CONTROL_BREAK then
Break;
end
else
begin
Log(ltFatal, 'Unexpected exception during tracing: ' + IntToHex(Ev.Exception.ExceptionRecord.ExceptionCode, 8));
Exit;
end;
end;

else
Status := DBG_CONTINUE;
end;

ContinueDebugEvent(Ev.dwProcessId, Ev.dwThreadId, Status);
end;
end;

function TTracer.OnSingleStep(const Ev: TDebugEvent): Cardinal;
var
C: TContext;
begin
Inc(FCounter);
if (FLimit <> 0) and (FCounter > FLimit) then
begin
FLimitReached := True;
Log(ltInfo, 'Giving up trace due to instruction limit');
Exit(DBG_CONTROL_BREAK);
end;

C.ContextFlags := CONTEXT_CONTROL;
if not GetThreadContext(FThreadHandle, C) then
RaiseLastOSError;

C.EFlags := C.EFlags or $100;
if not SetThreadContext(FThreadHandle, C) then
RaiseLastOSError;

if FPredicate(C) then
Result := DBG_CONTROL_BREAK
else
Result := DBG_CONTINUE;
end;

end.
2 changes: 1 addition & 1 deletion Unit2.dfm
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ object ThemidaUnpackerWnd: TThemidaUnpackerWnd
Left = 200
Top = 32
Bitmap = {
494C010103000800540010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
494C0101030008005C0010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
0000000000003600000028000000400000001000000001002000000000000010
0000000000000000000000000000000000000000000000000000000000000000
0000F6EAE420DBA6898FCE8155CFCC6B35FFCF7139FFD68757CFE5AE8C8FF9ED
Expand Down
6 changes: 2 additions & 4 deletions Unit2.pas
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, StdCtrls, Debugger, ComCtrls, ImgList;
Controls, Forms, Dialogs, StdCtrls, Debugger, ComCtrls, ImgList, Utils;

type
TThemidaUnpackerWnd = class(TForm)
Expand All @@ -20,8 +20,6 @@ TThemidaUnpackerWnd = class(TForm)
procedure btnShrinkClick(Sender: TObject);
procedure btnMakeDataSectClick(Sender: TObject);
private
FDbg: TDebugger;

procedure Log(MsgType: TLogMsgType; const Msg: string);
end;

Expand All @@ -45,7 +43,7 @@ procedure TThemidaUnpackerWnd.btnUnpackClick(Sender: TObject);
begin
if OD.Execute then
begin
FDbg := TDebugger.Create(OD.FileName, '', Log);
TDebugger.Create(OD.FileName, '', Log).FreeOnTerminate := True;
end;
end;

Expand Down
4 changes: 4 additions & 0 deletions Utils.pas
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ interface

uses Windows, SysUtils;

type
TLogMsgType = (ltInfo, ltGood, ltFatal);
TLogProc = procedure(MsgType: TLogMsgType; const Msg: string) of object;

function NtQueryInformationProcess(ProcessHandle: THandle; ProcessInformationClass: DWORD;
ProcessInformation: Pointer; ProcessInformationLength: DWORD; ReturnLength: PCardinal): Integer; stdcall; external 'ntdll.dll';
function NtQueryInformationThread(ThreadHandle: THandle; ThreadInformationClass: DWORD;
Expand Down
46 changes: 46 additions & 0 deletions scylla_hide.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
[SETTINGS]
CurrentProfile=Magicmida
[Magicmida]
DLLNormal=1
DLLStealth=0
DLLUnload=0
GetLocalTimeHook=0
GetSystemTimeHook=0
GetTickCount64Hook=0
GetTickCountHook=0
KiUserExceptionDispatcherHook=1
NtCloseHook=0
NtContinueHook=1
NtCreateThreadExHook=0
NtGetContextThreadHook=1
NtQueryInformationProcessHook=1
NtQueryObjectHook=0
NtQueryPerformanceCounterHook=0
NtQuerySystemInformationHook=1
NtQuerySystemTimeHook=0
NtSetContextThreadHook=0
NtSetDebugFilterStateHook=0
NtSetInformationThreadHook=1
NtSetInformationProcessHook=0
NtUserBlockInputHook=0
NtUserBuildHwndListHook=0
NtUserFindWindowExHook=0
NtUserQueryWindowHook=0
NtUserGetForegroundWindowHook=1
NtYieldExecutionHook=0
OutputDebugStringHook=0
PebBeingDebugged=1
PebHeapFlags=1
PebNtGlobalFlag=1
PebStartupInfo=0
PebOsBuildNumber=0
PreventThreadCreation=0
RemoveDebugPrivileges=0
AutostartServer=1
ServerPort=1337
BreakOnTLS=1
FixOllyBugs=1
RemoveEPBreak=0
SkipEPOutsideCode=1
X64Fix=1
WindowTitle=Themida

0 comments on commit 5c70453

Please sign in to comment.