Syntax10.Scn.FntSyntax10b.Scn.Fnto MarkElemsAllocr*Syntax10i.Scn.Fnt-(}**T3MODULE CtrlC; IMPORT S := SYSTEM, Kernel, Modules, Console; CONST CtrlCEvent = 0; CtrlBreakEvent = 1; CtrlCloseEvent = 2; CtrlLogoffEvent = 5; CtrlShutDownEvent = 6; infinite = 0FFFFFFFFH; TYPE HandlerProc = PROCEDURE (ctrlType: LONGINT): BOOLEAN; ThreadProc = PROCEDURE (par: LONGINT): LONGINT; FloatingSaveArea = RECORD ControlWord, StatusWord, TagWord, ErrorOffset, ErrorSelector, DataOffset, DataSelector: LONGINT; RegisterArea: ARRAY 80 OF S.BYTE; Cr0NpxState: LONGINT END ; ContextDesc = RECORD ContextFlags: LONGINT; Dr0, Dr1, Dr2, Dr3, Dr6, Dr7: LONGINT; FloatSave: FloatingSaveArea; SegGs, SegFs, SegEs, SegDs: LONGINT; Edi, Esi, Ebx, Edx, Ecx, Eax: LONGINT; Ebp, Eip, SegCs, EFlags, Esp, SegSs: LONGINT; END ; VAR installed: BOOLEAN; loopThread, trapThread, trapThreadId, event: LONGINT; context: ContextDesc; trap: ARRAY 2 OF CHAR; pc*: LONGINT; instr*: INTEGER; SetConsoleCtrlHandler: PROCEDURE (proc: HandlerProc; add: BOOLEAN): BOOLEAN; GetThreadContext: PROCEDURE (handle: LONGINT; context: LONGINT): BOOLEAN; GetCurrentThread: PROCEDURE (): LONGINT; GetCurrentProcess: PROCEDURE (): LONGINT; SuspendThread: PROCEDURE (handle: LONGINT): LONGINT; ResumeThread: PROCEDURE (handle: LONGINT): LONGINT; CreateThread: PROCEDURE (sa: LONGINT; stackSize: LONGINT; p: ThreadProc; par: LONGINT; createFlags: LONGINT; VAR id: LONGINT): LONGINT; ReadProcessMemory: PROCEDURE (handle, baseAdr, bufAdr, size: LONGINT; VAR nofRead: LONGINT): BOOLEAN; GetLastError: PROCEDURE (): LONGINT; DuplicateHandle: PROCEDURE (srcProcess, srcHandle, destProcess: LONGINT; VAR destHandle: LONGINT; access: LONGINT; inheritHandle: BOOLEAN; options: LONGINT): BOOLEAN; CreateEvent: PROCEDURE (sa: LONGINT; manualReset, initiallySet: BOOLEAN; name: LONGINT): LONGINT; SetEvent: PROCEDURE (handle: LONGINT): BOOLEAN; WaitForSingleObject: PROCEDURE (handle: LONGINT; timeout: LONGINT): LONGINT; (* PROCEDURE Min (x, y: LONGINT): LONGINT; BEGIN IF x < y THEN RETURN x ELSE RETURN y END END Min; PROCEDURE DumpStack (bp, sp: LONGINT); VAR i, size, nofRead: LONGINT; done: BOOLEAN; buf: ARRAY 256 OF LONGINT; BEGIN REPEAT size := bp - sp + 4; REPEAT done := ReadProcessMemory(GetCurrentProcess(), sp, S.ADR(buf), Min(size, 1024), nofRead); Console.Ln; Console.Str("From sp="); Console.Int(sp); Console.Str(", nofBytes: "); Console.Int(Min(size, 1024)); IF done THEN FOR i := 0 TO nofRead DIV 4 - 1 DO Console.Hex(buf[i]) END ELSE Console.Str("Could not read process memory"); i := GetLastError(); Console.Str(", error code: "); Console.Int(i); END ; DEC(size, nofRead); INC(sp, nofRead) UNTIL (size <= 0) OR ~done; bp := buf[nofRead DIV 4 - 1] UNTIL (sp = 0) OR (bp < sp) OR ~done (* plausibility checks: bp >= sp, sp # 0 *) END DumpStack; *) PROCEDURE TrapProc (par: LONGINT): LONGINT; VAR ret: LONGINT; m: Modules.Module; BEGIN LOOP ret := WaitForSingleObject(event, infinite); ret := SuspendThread(loopThread); context.ContextFlags := 10003H; IF GetThreadContext(loopThread, S.ADR(context)) THEN Console.Str("EDI ="); Console.Hex(context.Edi); Console.Ln; Console.Str("ESI ="); Console.Hex(context.Esi); Console.Ln; Console.Str("EBX ="); Console.Hex(context.Ebx); Console.Ln; Console.Str("EDX ="); Console.Hex(context.Edx); Console.Ln; Console.Str("ECX ="); Console.Hex(context.Ecx); Console.Ln; Console.Str("EAX ="); Console.Hex(context.Eax); Console.Ln; Console.Str("EBP ="); Console.Int(context.Ebp); Console.Ln; Console.Str("EIP ="); Console.Int(context.Eip); Console.Ln; Console.Str("CS ="); Console.Hex(context.SegCs); Console.Ln; Console.Str("EFLAGS ="); Console.Hex(context.EFlags); Console.Ln; Console.Str("ESP ="); Console.Int(context.Esp); Console.Ln; Console.Str("SS ="); Console.Hex(context.SegSs); Console.Ln; m := Kernel.modules; WHILE (m # NIL) & ((context.Eip < S.ADR(m.code^)) OR (S.ADR(m.code^) + LEN(m.code^) < context.Eip)) DO m := m.next END ; IF m # NIL THEN pc := context.Eip; S.GET(pc, instr); S.PUT(pc, S.VAL(INTEGER, trap)) END ; (* DumpStack(context.Ebp, context.Esp) *) ELSE Console.Str("Could not get thread context") END ; ret := ResumeThread(loopThread); END END TrapProc; PROCEDURE CtrlC (ctrlType: LONGINT): BOOLEAN; VAR EBX, ESI, EDI: LONGINT; retval, done: BOOLEAN; dummy: LONGINT; BEGIN S.GETREG(3, EBX); S.GETREG(6, ESI); S.GETREG(7, EDI); CASE ctrlType OF CtrlCEvent, CtrlBreakEvent: done := SetEvent(event); retval := TRUE ELSE retval := FALSE END ; S.PUTREG(3, EBX); S.PUTREG(6, ESI); S.PUTREG(7, EDI); RETURN retval END CtrlC; PROCEDURE TermHandler; VAR done: BOOLEAN; BEGIN IF installed THEN done := SetConsoleCtrlHandler(CtrlC, FALSE) END END TermHandler; PROCEDURE Init; VAR mod: LONGINT; done: BOOLEAN; BEGIN mod := Kernel.LoadLibrary("Kernel32"); Kernel.GetAdr(mod, "SetConsoleCtrlHandler", S.VAL(LONGINT, SetConsoleCtrlHandler)); installed := SetConsoleCtrlHandler(CtrlC, TRUE); IF ~installed THEN RETURN END ; Kernel.GetAdr(mod, "GetThreadContext", S.VAL(LONGINT, GetThreadContext)); Kernel.GetAdr(mod, "GetCurrentThread", S.VAL(LONGINT, GetCurrentThread)); Kernel.GetAdr(mod, "GetCurrentProcess", S.VAL(LONGINT, GetCurrentProcess)); Kernel.GetAdr(mod, "ResumeThread", S.VAL(LONGINT, ResumeThread)); Kernel.GetAdr(mod, "SuspendThread", S.VAL(LONGINT, SuspendThread)); Kernel.GetAdr(mod, "CreateThread", S.VAL(LONGINT, CreateThread)); Kernel.GetAdr(mod, "ReadProcessMemory", S.VAL(LONGINT, ReadProcessMemory)); Kernel.GetAdr(mod, "GetLastError", S.VAL(LONGINT, GetLastError)); Kernel.GetAdr(mod, "DuplicateHandle", S.VAL(LONGINT, DuplicateHandle)); Kernel.GetAdr(mod, "CreateEventA", S.VAL(LONGINT, CreateEvent)); Kernel.GetAdr(mod, "SetEvent", S.VAL(LONGINT, SetEvent)); Kernel.GetAdr(mod, "WaitForSingleObject", S.VAL(LONGINT, WaitForSingleObject)); Kernel.InstallTermHandler(TermHandler); mod := Kernel.LoadLibrary("USER32"); loopThread := GetCurrentThread(); done := DuplicateHandle(GetCurrentProcess(), loopThread, GetCurrentProcess(), loopThread, 0, FALSE, 2 (* DUPLICATE_SAME_ACCESS *)); event := CreateEvent(0, FALSE, FALSE, S.ADR("OBERONCTRLC")); trapThread := CreateThread(0, 0, TrapProc, 0, 0, trapThreadId); trap[0] := 8DX; trap[1] := 0C9X; (* lea ecx, ecx *) END Init; BEGIN Init END CtrlC.ShowMode CtrlC.Endless System.Free Break ~ Debugger.Data CtrlC