.386 .model flat,stdcall option casemap:none include include\windows.inc include include\kernel32.inc include include\comdlg32.inc include include\user32.inc includelib lib\kernel32.lib includelib lib\comdlg32.lib includelib lib\user32.lib .data AppName db "JumpLogger v1.0 by defiler (thx for debug-api stuff by Iczelion)",0 ofn OPENFILENAME <> FilterString db "Executable Files",0,"*.exe",0 db "All Files",0,"*.*",0,0 ExitProc db "The debuggee exits",0 TotalInstruction dd 0 LogFile db 'jumplog.log',0 Handle dd 0 THandle dd 0 written dd 0 FileAttr dd 0 ReportInts db 1 RVA db 8 dup(0) db ': ' JumpAddr db 8 dup(0) db ' ' _Flags db 0 db 'Flags: ' Overflow db 0 Direction db 0 Interrupt db 0 Trap db 0 Sign db 0 Zero db 0 Auxiliary db 0 Parity db 0 Carry db 0 SizeOfFlags equ $-offset _Flags-1 Code db 8 dup(0) db 8 dup(020h) Opcode dd 0 backup dd 0 CRLF db 13,10 ProcHandle dd 0 Opcodes db 077h ;opcode-table for conditional jumps listed below db 073h db 072h db 076h db 0E3h db 074h db 07Fh db 07Dh db 07Ch db 07Eh db 075h db 071h db 07Bh db 079h db 070h db 07Ah db 078h mnemonics db 0 ;list of mnemonics used for disassembly _JA db 'ja ' _JAE db 'jae ' _JB db 'jb ' _JBE db 'jbe ' _JCXZ db 'jcxz ' _JZ db 'jz ' _JG db 'jg ' _JGE db 'jge ' _JL db 'jl ' _JLE db 'jle ' _JNZ db 'jnz ' _JNO db 'jno ' _JNP db 'jnp ' _JNS db 'jns ' _JO db 'jo ' _JP db 'jp ' _JS db 'js ' msg db 'Possible Debugger detection! Try to remove (lame patching)?',0 cap db 'hmmm...',0 NopArray db 10 dup(090h) .data? buffer db 512 dup(?) startinfo STARTUPINFO <> pi PROCESS_INFORMATION <> DBEvent DEBUG_EVENT <> align dword context CONTEXT <> .code main: mov [FileAttr],0 ;parameters for GetOpenFileName mov ofn.lStructSize,SIZEOF ofn mov ofn.lpstrFilter, OFFSET FilterString mov ofn.lpstrFile, OFFSET buffer mov ofn.nMaxFile,512 mov ofn.Flags, OFN_FILEMUSTEXIST or \ OFN_PATHMUSTEXIST or OFN_LONGNAMES or\ OFN_EXPLORER or OFN_HIDEREADONLY invoke GetOpenFileName, ADDR ofn ;open dialog .if eax==TRUE ;################## ;create log-file (file will always be overwritten, if previously existed) invoke CreateFileA,ADDR LogFile,GENERIC_READ or GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0 mov [Handle],eax ;################# ;Create the process of the chosen .exe ;and handle debug-events invoke GetStartupInfo,addr startinfo invoke CreateProcess, addr buffer, NULL, NULL, NULL, FALSE, DEBUG_PROCESS+ DEBUG_ONLY_THIS_PROCESS, NULL, NULL, addr startinfo, addr pi .while TRUE invoke WaitForDebugEvent, addr DBEvent, INFINITE ;'suspend' our debugger until an .if DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT ;exception occurs mov eax,DBEvent.u.CreateProcessInfo.hProcess mov [ProcHandle], eax ;skip the ep-exception .elseif DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT ;process killed/exited ? invoke MessageBox, 0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION .break .elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT ;breakpoint? .if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT mov context.ContextFlags, CONTEXT_CONTROL invoke GetThreadContext, pi.hThread, addr context ;'pop' registers or context.regFlag,100h ;set trap-flag invoke SetThreadContext,pi.hThread, addr context ;'push' registers invoke ContinueDebugEvent, DBEvent.dwProcessId,DBEvent.dwThreadId,DBG_CONTINUE ;continue debuggee .continue .elseif DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_SINGLE_STEP ;set the trapflag previously? invoke GetThreadContext,pi.hThread,addr context ;get flags and other shit call Log ;call a poorly commented log-procedure or context.regFlag,100h ;set the trap flag invoke SetThreadContext,pi.hThread, addr context ;ficke,ficke invoke ContinueDebugEvent, DBEvent.dwProcessId,DBEvent.dwThreadId,DBG_CONTINUE .continue .endif .endif invoke ContinueDebugEvent, DBEvent.dwProcessId,DBEvent.dwThreadId,DBG_EXCEPTION_NOT_HANDLED ;this must be window's or coder's fault ;) .endw .endif ;################# ;fixup and stuff... invoke TerminateProcess,pi.hProcess,0 ;quit debugee invoke CloseHandle,pi.hProcess ;close handle for debugee invoke CloseHandle,pi.hThread invoke CloseHandle,Handle invoke ExitProcess,0 ;exit JumpLog ;################# ;some procs ;converts a dword into hexadecimal format and copies it to a given string buffer DecToHex Proc mov ecx,8 ;init counter xor ebx, ebx mov eax, [esp+4] ;1st param = decimal(dword) to convert mov edi, [esp+8] ;2nd param = pointer to ascii-buffer calc: dec ecx ;decrement counter mov bl, al shl bl,4 shr bl,4 add bl, 030h cmp bl,3Ah jb nofix add bl,7 nofix: mov byte ptr [edi+ecx],bl dec ecx mov bl, al shr bl,4 add bl, 030h cmp bl,3Ah jb nofix2 add bl,7 nofix2: mov byte ptr [edi+ecx],bl shr eax,8 test ecx, ecx jnz calc ret 8 DecToHex endp ;################# ;create disassembly and collect some shitty info and write it to our logfile Log Proc pushad ;save all regs invoke ReadProcessMemory, [ProcHandle], context.regEip ,ADDR Opcode, 4, ADDR written ;read 4 bytes at EIP mov ebx,[Opcode] mov [backup],ebx ;################# ;check for conditional jumps cmp bl, 074h ;jz ? jz GetFlags cmp bl, 075h ;jnz? jz GetFlags cmp bl, 07Dh ;jge ? jz GetFlags cmp bl, 07Fh ;jg ? jz GetFlags cmp bl, 077h ;ja ? jz GetFlags cmp bl, 073h ;jae ? jz GetFlags cmp bl, 072h ;jb ? jz GetFlags cmp bl, 076h ;jbe ? jz GetFlags cmp bl, 0E3h ;jcxz ? jz GetFlags cmp bl, 07Ch ;jl ? jz GetFlags cmp bl, 07Eh ;jle ? jz GetFlags cmp bl, 071h ;jno ? jz GetFlags cmp bl, 07Bh ;jnp ? jz GetFlags cmp bl, 079h ;jns ? jz GetFlags cmp bl, 070h ;jo ? jz GetFlags cmp bl, 07Ah ;jp ? jz GetFlags cmp bl, 078h ;js ? jz GetFlags ;################# ;check for possible sice detections ;int 3 ? cmp bl, 0CCh jz int3call ;int 1 ? cmp bx, 001CDh jz intcall ;int 68h ? cmp bx, 068CDh jz intcall ;no more sice detections included ;) jmp skip GetFlags: mov eax, context.regFlag ;store flags into eax ;################# ;test for specific flags CheckC: test eax, 0000000000000001b jnz Cset mov [Carry],'c' jmp CheckP Cset: mov [Carry],'C' CheckP: test eax, 0000000000000100b jnz Pset mov [Parity],'p' jmp CheckA Pset: mov [Parity],'P' CheckA: test eax, 0000000000010000b jnz Aset mov [Auxiliary],'a' jmp CheckZ Aset: mov [Auxiliary],'A' CheckZ: test eax, 0000000001000000b jnz Zset mov [Zero],'z' jmp CheckS Zset: mov [Zero],'Z' CheckS: test eax, 0000000010000000b jnz Sset mov [Sign],'s' jmp CheckT Sset: mov [Sign],'S' CheckT: test eax, 0000000100000000b jnz Tset mov [Trap],'t' jmp CheckI Tset: mov [Trap],'T' CheckI: test eax, 0000001000000000b jnz Iset mov [Interrupt],'i' jmp CheckD Iset: mov [Interrupt],'I' CheckD: test eax, 0000010000000000b jnz Dset mov [Direction],'d' jmp CheckO Dset: mov [Direction],'D' CheckO: test eax, 0000100000000000b jnz Oset mov [Overflow],'o' jmp done Oset: mov [Overflow],'O' done: push offset RVA push context.regEip call DecToHex ;convert current eip to hex for the dump to log-file mov eax,[Opcode] ;erm, lame routine to swap some bytes mov bl,al mov cl,ah mov ah,bl mov al,cl shl eax, 16 mov [Opcode], eax push offset Code push [Opcode] call DecToHex ;convert the opcode to hex mov dword ptr [Code+4],020202020h ;add some spaces ;################# ;write to log-file invoke WriteFile,[Handle],ADDR RVA,10,ADDR written,0 ;write eip to log invoke WriteFile,[Handle],ADDR Code,10,ADDR written,0 ;write opcodes ;################# ;create disassembly opcode ;int 3 cld mov ecx,17 mov eax, [backup] mov edi, offset Opcodes repnz scasb mov edx, 17 sub edx, ecx mov esi, offset mnemonics inc esi dec edx mov eax,5 mul edx add esi, eax invoke WriteFile,[Handle],esi,5,ADDR written,0 ;create disassembly operand mov eax, context.regEip mov ebx,[backup] add bh,2 add al, bh push offset JumpAddr push eax call DecToHex invoke WriteFile,[Handle],ADDR JumpAddr,10,ADDR written,0 invoke WriteFile,[Handle],ADDR _Flags+1,SizeOfFlags,ADDR written,0 invoke WriteFile,[Handle],addr CRLF,2,ADDR written,0 skip: popad ret int3call: cmp [ReportInts],0 jz skip invoke MessageBoxA,0,addr msg,addr cap,MB_YESNOCANCEL+MB_ICONEXCLAMATION cmp eax,IDNO ;no ? jz skip cmp eax,IDCANCEL jz neverask invoke WriteProcessMemory,[ProcHandle],context.regEip ,addr NopArray, 1, NULL jmp skip intcall: cmp [ReportInts],0 jz skip invoke MessageBoxA,0,addr msg,addr cap,MB_YESNOCANCEL+MB_ICONEXCLAMATION cmp eax,IDNO ;no ? jz skip invoke WriteProcessMemory,[ProcHandle],context.regEip ,addr NopArray, 2, NULL jmp skip neverask: mov [ReportInts],0 jmp skip Log endp end main