您的位置:首页 > 编程语言 > Python开发

Python逆向工程笔记

2013-03-01 12:50 232 查看
Python的ctypes模块可以动态调用链接库,能够生成复杂的C语言的数据类型,可以运用底层的内存管理函数。

Debugger是黑客的掌上明珠(apple of hacker's eye)。运用debugger,能够在运行时跟踪进程,或是动态分析。有两种不同的黒盒debugger:用户模式和内核模式。用户模式的用于逆向工程和黑客的debugger有WinDbg(win),OllyDbg(win),gdb(*nix),这几个debugger各有千秋。智能debugger有很大的优势,尤其在windows平台上。智能debugger必须是脚本化的,能够支持各种扩展特性如hooking,以及其他bug hunting和逆向工程的高级特性。其中较好的是PyDbg和Immunity Debugger。

PyDbg是纯粹的Python程序,允许黑客对进程进行全面自动的控制。Immunity Debugger包括了很多的Python的调试库。

Debug Events

Debugger不停循环,等待一个debugging event出现。当一个debugging event出现,循环停止,一个对应的handler被调用。此时debugger在等待如何继续的指令。一些通常的debugger必须处理的events有:

Breakpoint hit

Memory violation(such as segment fault)

Exception generated by the debugged program

有些OS也会dispatch其他的events到debugger,比如线程和进程的创建,载入动态库。

Breakpoints

同过暂停程序,我们可以了解程序当前的运行状况。breakpoints主要有三种:soft breakpoints,hardware breakpoints以及memory breakpoints。他们有相似的行为,但是实现不同。

Soft Breakpoints

这是目前最common的类型。该breakpoint修改指令的opcode,改成Int 3的指令。当debugger设置breakpoint的时候,其读被设breakpoint的指令的第一个opcode byte,然后存储该byte。接着用Int 3指令覆盖该byte。当CPU执行到Int 3,调用handler,handler检查EIP,找到存储的opcode,将其写回。警告:当我们改变内存中的可执行的byte的时候,我们改变了软件的cyclic redundancy check (CRC) checksum。CRC是用于用于判断数据是否被改变过了。很多恶意软件也会检查其自身的CRC,这个限制了软中断的使用,限制动态分析,使得逆向工程更加困难。如果要避免这些缺点,必须使用硬中断。

Hardware Breakpoints

当只需要设置少量的breakpoint,且被调试程序无法被更改的时候,Hardware Breakpoints较为有用。这种断点是在CPU层面设置的, 在CPU内有些特殊的debug寄存器,典型的CPU有(DR0-DR7)总计8个寄存器。DR0-DR3用于保存断点地址,所以同时最多设4个断点。DR4-DR5是保留的,DR6是状态寄存器,决定哪个debug event被触发。DR7是debug的开关,也存储各个断点的条件。通过在DR7中设置不同的flag,能够生成下面条件的断点:

指定地址的指令执行时break

指定地址被写入的时候break

指定地址被读或写但不执行的时候break

hardware breakpoints采用Int 1中断。Int 1 event是hardware中断,是single-step-events,允许在监测数据改变的时候,closely inspect 代码关键部分。

Memory Breakpoints

这不是真正意义上的breakpoints。其改变了内存区域的permission。总共有下面这几个permission:Page Execution,Page Read,Page Write,Guard Page(Any access to such page results in one-time execption,然后恢复)

Build a windows debugger

若欲在一个进程上debug,首先必须用某种方式将debugger与进程关联起来。因此,debugger必须能够打开一个可执行文件,运行之或者attach到该运行的进程上。Windows的debugging API提供了简单的方法。新建进程与连接进程有所不同。新建进程的有点是能够在进程运行之前控制该进程。但是这种方法应用在恶意软件及其他恶意代码的时候却很困难。attach方式插入已在运行的进程,跳过不重要的区域,直接观察感兴趣的代码。对于新建进程,windows有个CreateProcessA函数。对于第二种方法,windows提供OpenProcess,DebugActiveProcess函数。获得当前线程用OpenThread。枚举线程用CreateToolhelp32Snapshot,Thread32First,Thread32Next。采用WaitForDebugEvent监听event。

 



Debug Event

 

Soft Breakpoint是通过修改程序的内存来实现的。因此采用windows提供的ReadProcessMemory和WriteProcessMemory两个函数就行了。

Hard BreakPoint是通过设置CPU的flag实现。因此首先需要获得每个线程的context record,然后修改其中的CPU寄存器。

Memory Breakpoint是通过 GetSystemInfo函数获得页的相关信息(比如页面大小),然后VirtualQueryEx函数查询该页的基本信息,VirtualProtectEx修改页的权限。

Exploit Development

找到Exploit-friendly指令,比如jmp esp之类的。

过滤bad-character,比如如果想用strcpy的overflow,那么不能包含0x00。

通过windows的DEP防护(防止执行数据块的代码)。windows提供了关掉进程自己的DEP的API:NtSetInformationProcess。因为传入的参数有些是0x00所以不能直接通过strcpy来搞,可以考虑利用栈上的已经存在的数据当作参数。所以先overflow后将return address改写,调用NtSetInformationProcess,该return address的上面写上我们overflow的代码的address,这样最终能调用到插入的代码。

 

与恶意软件中的反debug机制斗争

现在的恶意软件除了代码混淆,还采用打包,加密等技术,他们呢也有一套anti-debug的机制,以防别人利用debug机制了解其行为。可能会有以下机制:

调用window的API检测是否存在Debugger。windows提供IsDebuggerPresent函数,该函数返回当前的进程有没有debugger连接上去。该函数主要load进程环境块(PEB),然后返回其中其中的关于是否存在debugger的值。因此避开检测可以直接修改当前进程PEB中的值。

恶意软件也会枚举所有的进程来判断是否有debugger。可以给枚举进程的函数打个补丁,使其永远不返回true。这个在Immunity Debugger中有工具可以方便地做这件事。

Hooking

主要有两种hook,soft和hard。soft hook,连接到了目标进程,运用Int 3断点handler来实现。hard hook是采用硬编码,jump到制定的指令。soft hook适用于非紧迫且非经常调用的函数。如果要hook经常调用且对于debugee影响最小的话(紧迫的I/O操作,堆管理),那么需要hard hook。

soft hook应用实例:在应用层面嗅探加密的数据。如果单单用wireshark等工具,只能看到加密的包。使用soft hook能够在加密前或解密后获得数据。以firefox为例,用https来浏览网页,当接受到一个SSL的凭证,将debugger连接到firefox.exe的进程,在加密函数的入口设置断点,貌似是nspr4.PR_Write。当传输数据的时候,就可以捕获到了。PyDbg中有相应的工具设置soft hook。

如果需要在hook的handler期间能够响应某些event,那么应当用hard hook。Immunity Debugger中有相应工具。建立stub,然后将原来的代码写成跳到stub的指令。

DLL&代码注入

DLL注入和代码注入有很多区别,但是都有共同的行为:remote thread creation。windows有API(CreateRemoteThread)来干这事。

DLL注入

安全软件也是通过DLL注入来监测恶意进程的。windows有接口LoadLibrary载入DLL。首先需要分配给DLL加载路径的内存,接着将DLL路径写入内存,再载入DLL,最后CreateRmoteThread。

Code注入

将代码写入内存,然后通过新建一个线程来执行代码。

隐藏执行文件。比如利用NTFS的alternate data stream(ADS)机制,该机制允许将一个可执行文件放在磁盘上,将DLL放在主可执行文件关联的stream上。这样用户不能直接看到DLL。很多安全软件也没有仔细检查ADS。

Fuzzing

发送恶意数据试图使程序产生错误,这是找出程序bug的一种方式。有两种fuzzers: generation和mutation fuzzers。Generation fuzzers生成要发送的数据,mutation fuzzers利用已经存在的数据,修改之。

Bug Classes:Buffer Overflow,Integer Overflows,format String Attacks

Python-based fuzzing framework:Sulley

disassembler:IDA PRO

Python的模拟器:PyEmu
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: