Skip to content

Instantly share code, notes, and snippets.

@196Ikuchil
Last active February 18, 2023 10:34
Show Gist options
  • Select an option

  • Save 196Ikuchil/2cd5e900541cff606bfa51a2f86e4e0a to your computer and use it in GitHub Desktop.

Select an option

Save 196Ikuchil/2cd5e900541cff606bfa51a2f86e4e0a to your computer and use it in GitHub Desktop.
リバースエンジニアリング Pythonによるバイナリ解析技法 3.2 python3.7.0
from ctypes import *
# Let's map the Microsoft types to ctypes for clarity
BYTE = c_ubyte
WORD = c_ushort
DWORD = c_ulong
DWORD64 = c_ulonglong
LPBYTE = POINTER(c_ubyte)
LPTSTR = POINTER(c_char)
HANDLE = c_void_p
PVOID = c_void_p
LPVOID = c_void_p
UINT_PTR = c_ulong
SIZE_T = c_ulong
ULONG_PTR = c_ulong
LONGLONG = c_longlong
ULONGLONG = c_ulonglong
# Constants
DEBUG_PROCESS = 0x00000001
CREATE_NEW_CONSOLE = 0x00000010
PROCESS_ALL_ACCESS = 0x001F0FFF
INFINITE = 0xFFFFFFFF
DBG_CONTINUE = 0x00010002
DBG_EXCEPTION_NOT_HANDLED = 0x80010001
# Debug event constants
EXCEPTION_DEBUG_EVENT = 0x1
CREATE_THREAD_DEBUG_EVENT = 0x2
CREATE_PROCESS_DEBUG_EVENT = 0x3
EXIT_THREAD_DEBUG_EVENT = 0x4
EXIT_PROCESS_DEBUG_EVENT = 0x5
LOAD_DLL_DEBUG_EVENT = 0x6
UNLOAD_DLL_DEBUG_EVENT = 0x7
OUTPUT_DEBUG_STRING_EVENT = 0x8
RIP_EVENT = 0x9
# debug exception codes.
EXCEPTION_ACCESS_VIOLATION = 0xC0000005
EXCEPTION_BREAKPOINT = 0x80000003
EXCEPTION_GUARD_PAGE = 0x80000001
EXCEPTION_SINGLE_STEP = 0x80000004
# Thread constants for CreateToolhelp32Snapshot()
TH32CS_SNAPHEAPLIST = 0x00000001
TH32CS_SNAPPROCESS = 0x00000002
TH32CS_SNAPTHREAD = 0x00000004
TH32CS_SNAPMODULE = 0x00000008
TH32CS_INHERIT = 0x80000000
TH32CS_SNAPALL = (TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE)
THREAD_ALL_ACCESS = 0x001F03FF
# Context flags for GetThreadContext()
CONTEXT_AMD64 = 0x00100000
CONTEXT_CONTROL = CONTEXT_AMD64|0x00000001
CONTEXT_INTEGER = CONTEXT_AMD64|0x00000002
CONTEXT_SEGMENTS = CONTEXT_AMD64|0x00000004
CONTEXT_FLOATING_POINT = CONTEXT_AMD64|0x00000008
CONTEXT_DEBUG_REGISTERS = CONTEXT_AMD64|0x00000010
CONTEXT_FULL = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT
CONTEXT_ALL = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_SEGMENTS|CONTEXT_FLOATING_POINT|CONTEXT_DEBUG_REGISTERS
# Memory permissions
PAGE_EXECUTE_READWRITE = 0x00000040
# Hardware breakpoint conditions
HW_ACCESS = 0x00000003
HW_EXECUTE = 0x00000000
HW_WRITE = 0x00000001
# Memory page permissions, used by VirtualProtect()
PAGE_NOACCESS = 0x00000001
PAGE_READONLY = 0x00000002
PAGE_READWRITE = 0x00000004
PAGE_WRITECOPY = 0x00000008
PAGE_EXECUTE = 0x00000010
PAGE_EXECUTE_READ = 0x00000020
PAGE_EXECUTE_READWRITE = 0x00000040
PAGE_EXECUTE_WRITECOPY = 0x00000080
PAGE_GUARD = 0x00000100
PAGE_NOCACHE = 0x00000200
PAGE_WRITECOMBINE = 0x00000400
# Structures for CreateProcessA() function
# STARTUPINFO describes how to spawn the process
class STARTUPINFO(Structure):
_fields_ = [
("cb", DWORD),
("lpReserved", LPTSTR),
("lpDesktop", LPTSTR),
("lpTitle", LPTSTR),
("dwX", DWORD),
("dwY", DWORD),
("dwXSize", DWORD),
("dwYSize", DWORD),
("dwXCountChars", DWORD),
("dwYCountChars", DWORD),
("dwFillAttribute",DWORD),
("dwFlags", DWORD),
("wShowWindow", WORD),
("cbReserved2", WORD),
("lpReserved2", LPBYTE),
("hStdInput", HANDLE),
("hStdOutput", HANDLE),
("hStdError", HANDLE),
]
# PROCESS_INFORMATION receives its information
# after the target process has been successfully
# started.
class PROCESS_INFORMATION(Structure):
_fields_ = [
("hProcess", HANDLE),
("hThread", HANDLE),
("dwProcessId", DWORD),
("dwThreadId", DWORD),
]
class EXCEPTION_RECORD(Structure):
pass
EXCEPTION_RECORD._fields_ = [
("ExceptionCode", DWORD),
("ExceptionFlags", DWORD),
("ExceptionRecord", POINTER(EXCEPTION_RECORD)),
("ExceptionAddress", PVOID),
("NumberParameters", DWORD),
("ExceptionInformation", ULONG_PTR*15),
]
class _EXCEPTION_RECORD(Structure):
_fields_ = [
("ExceptionCode", DWORD),
("ExceptionFlags", DWORD),
("ExceptionRecord", POINTER(EXCEPTION_RECORD)),
("ExceptionAddress", PVOID),
("NumberParameters", DWORD),
("ExceptionInformation", ULONG_PTR*15),
]
class EXCEPTION_DEBUG_INFO(Structure):
_fields_ = [
("ExceptionRecord", EXCEPTION_RECORD),
("dwFirstCance", DWORD),
]
class U(Union):
_fields_ = [
("Exception", EXCEPTION_DEBUG_INFO),
]
class DEBUG_EVENT(Structure):
_fields_ = [
("dwDebugEventCode", DWORD),
("dwProcessId", DWORD),
("dwThreadId", DWORD),
("u", U),
]
class M128A(Structure):
_fields_ = [
("Low", ULONGLONG),
("High", LONGLONG),
]
class XSAVE_FORMAT(Structure):
_fields_ = [
("ControlWord", WORD),
("StatusWord", WORD),
("TagWord", BYTE),
("Reservedl", BYTE),
("ErrorOpcode", WORD),
("ErrorOffset", DWORD),
("ErrorSelector", WORD),
("Reserved2", WORD),
("DataOffset", DWORD),
("DataSelector", WORD),
("Reserved3", WORD),
("MxCsr", DWORD),
("MxCsr_Mask", DWORD),
("FloatRegisters", M128A*8),
("XmmRegisters", M128A*16),
("Reserved4", BYTE*96),
]
class DUMMYSTRUCTNAME(Structure):
_fields_ = [
("Header", M128A*2),
("Legacy", M128A*8),
("Xmm0", M128A),
("Xmm1", M128A),
("Xmm2", M128A),
("Xmm3", M128A),
("Xmm4", M128A),
("Xmm5", M128A),
("Xmm6", M128A),
("Xmm7", M128A),
("Xmm8", M128A),
("Xmm9", M128A),
("Xmm10", M128A),
("Xmm11", M128A),
("Xmm12", M128A),
("Xmm13", M128A),
("Xmm14", M128A),
("Xmm15", M128A),
]
XMM_SAVE_AREA32 = XSAVE_FORMAT
class DUMMYUNIONNAME(Union):
_fields_ = [
("FltSave", XMM_SAVE_AREA32),
("dummystructname", DUMMYSTRUCTNAME)
]
class CONTEXT(Structure):
_fields_ = [
("P1Home", DWORD64),
("P2Home", DWORD64),
("P3Home", DWORD64),
("P4Home", DWORD64),
("P5Home", DWORD64),
("P6Home", DWORD64),
("ContextFlags", DWORD),
("MxCsr", DWORD),
("SegCs", WORD),
("SegDs", WORD),
("SegEs", WORD),
("SegFs", WORD),
("SegGs", WORD),
("SegSs", WORD),
("EFlags", DWORD),
("Dr0", DWORD64),
("Dr1", DWORD64),
("Dr2", DWORD64),
("Dr3", DWORD64),
("Dr6", DWORD64),
("Dr7", DWORD64),
("Rax", DWORD64),
("Rcx", DWORD64),
("Rdx", DWORD64),
("Rbx", DWORD64),
("Rsp", DWORD64),
("Rbp", DWORD64),
("Rsi", DWORD64),
("Rdi", DWORD64),
("R8", DWORD64),
("R9", DWORD64),
("R10", DWORD64),
("R11", DWORD64),
("R12", DWORD64),
("R13", DWORD64),
("R14", DWORD64),
("R15", DWORD64),
("Rip", DWORD64),
("dummyunionname", DUMMYUNIONNAME),
("VectorRegister", M128A*26),
("VectorControl", DWORD64),
("DebugControl", DWORD64),
("LastBranchToRip", DWORD64),
("LastBranchFromRip", DWORD64),
("LastExceptionToRip", DWORD64),
("LastExceptionFromRip", DWORD64),
]
# THREADENTRY32 contains information about a thread
# we use this for enumerating all of the system threads
class THREADENTRY32(Structure):
_fields_ = [
("dwSize", DWORD),
("cntUsage", DWORD),
("th32ThreadID", DWORD),
("th32OwnerProcessID", DWORD),
("tpBasePri", DWORD),
("tpDeltaPri", DWORD),
("dwFlags", DWORD),
]
from src.defines import*
from ctypes import *
from src import defines
kernel32 = windll.kernel32
class Debugger():
def __init__(self):
self.h_process = None
self.pid = None
self.debugger_active= False
self.h_thread = None
self.context = None
self.exception_address=None
self.software_breakpoints = {}
def load(self,path_to_exe):
#dwCreationFlag�ソスノゑソス�ソス
#�ソスユろせ�ソス�ソス�ソス�ソス�ソスヌのよう�ソスノ撰ソス�ソス�ソス�ソス�ソス�ソス驍ゥ�ソス�ソス�ソス�ソス�ソスワゑソス
#�ソスd�ソス�ソス�ソスGUI�ソス�ソス�ソス�ソス�ソス�ソス�ソス�ソス�ソス�ソス�ソス
# creation_flags = CREATE_NEW_CONSOLE�ソスニ設定す�ソス�ソス
creation_flags = DEBUG_PROCESS
#�ソス\�ソス�ソス�ソスフゑソス�ソスC�ソス�ソス�ソスX�ソス^�ソス�ソス�ソスX�ソス�ソス
startupinfo= STARTUPINFO()
process_information =PROCESS_INFORMATION()
#�ソスツゑソス�ソスフ2�ソスツのオ�ソスv�ソスV�ソス�ソス�ソス�ソス�ソスノゑソス�ソスf�ソスN�ソス�ソス�ソス�ソス�ソス黷ス�ソスv�ソス�ソス�ソスZ�ソスX�ソス�ソス
#�ソスハウ�ソスB�ソス�ソス�ソスh�ソスE�ソスニゑソス�ソスト表�ソス�ソス�ソス�ソス�ソス�ソス�ソス
#STARTUPINFO�ソス\�ソス�ソス�ソスフにゑソス�ソス�ソス�ソス�ソスン定が�ソスf�ソスo�ソスb�ソスO�ソスホ象ゑソス
#�ソスe�ソス�ソス�ソス�ソス�ソスy�ソスレゑソス�ソス�ソスナゑソス�ソス�ソス�ソス�ソス
startupinfo.dwFlags = 0x1
startupinfo.wShowWindow = 0x0
#STARTUPINFO�ソス\�ソス�ソス�ソスフのゑソス�ソス�ソス�ソス�ソス�ソス�ソス\�ソス�ソス�ソスマ撰ソスcd�ソス�ソス�ソス�ソス�ソス�ソス�ソス�ソス�ソス�ソス�ソス�ソス
startupinfo.cb=sizeof(startupinfo)
if kernel32.CreateProcessA(path_to_exe,
None,
None,
None,
None,
creation_flags,
None,
None,
byref(startupinfo),
byref(process_information)):
print ("*[*] PID: %d" % process_information.dwProcessId)
self.h_process = self.open_process(process_information.dwProcessId)
else:
print ("*[*] Error:0x%08x." % kernel32.GetLastError())
def open_process(self,pid):
handle = kernel32.OpenProcess(PROCESS_ALL_ACCESS,False,pid)
if not handle:
print (WinError(GetLastError()))
return handle
def attach(self,pid):
self.handle = self.open_process(pid)
if kernel32.DebugActiveProcess(pid):
self.debugger_active=True
self.pid=int(pid)
return True
else:
print(WinError(GetLastError()))
return False
def run(self):
while self.debugger_active:
self.get_debug_event()
def get_debug_event(self):
debug_event = DEBUG_EVENT()
if kernel32.WaitForDebugEvent(byref(debug_event),INFINITE):
input("press a key to continue...")
self.debugger_active=False
kernel32.ContinueDebugEvent(debug_event.dwProcessId,
debug_event.dwThreadId,
DBG_CONTINUE)
def detach(self):
if kernel32.DebugActiveProcessStop(self.pid):
print("[*] finished debugging. Exiting...")
return True
else:
print(WinError(GetLastError()))
return False
def open_thread(self,thread_id):
h_thread = kernel32.OpenThread(THREAD_ALL_ACCESS,None,thread_id)
if h_thread is not 0:
return h_thread
else:
print("[*] Could not obtain a valid thread handle.")
return False
def enumerate_threads(self):
thread_entry=THREADENTRY32()
thread_list = []
snapshot =kernel32.CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,self.pid)
if snapshot is not None:
thread_entry.dwSize = sizeof(thread_entry)
success = kernel32.Thread32First(snapshot,byref(thread_entry))
while success:
if thread_entry.th32OwnerProcessID == self.pid:
thread_list.append(thread_entry.th32ThreadID)
success = kernel32.Thread32Next(snapshot,byref(thread_entry))
kernel32.CloseHandle(snapshot)
return thread_list
else:
return False
def get_thread_context(self,thread_id=None,h_thread=None):
context = CONTEXT()
context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS
#get thread handle
if h_thread is None:
h_thread = self.open_thread(thread_id)
if kernel32.GetThreadContext(h_thread,byref(context)):
kernel32.CloseHandle(h_thread)
return context
else:
return False
from src.my_debugger import *
from src import my_debugger
debugger = my_debugger.Debugger()
# debugger.load("C:\\Windows\\System32\\calc.exe")
pid = int(input("PID: "))
debugger.attach(pid)
#debugger.run()
list = debugger.enumerate_threads()
for thread in list:
context = debugger.get_thread_context(thread)
print("[Rip]0x{:016X}".format(context.Rip))
print("[Rax]0x{:016X}".format(context.Rax))
print("[Rcx]0x{:016X}".format(context.Rcx))
print("[Rdx]0x{:016X}".format(context.Rdx))
print("[Rbx]0x{:016X}".format(context.Rbx))
print("[Rsp]0x{:016X}".format(context.Rsp))
print("[Rbp]0x{:016X}".format(context.Rsp))
print("[Rsi]0x{:016X}".format(context.Rsi))
print("[Rdi]0x{:016X}".format(context.Rdi))
debugger.detach()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment