diff --git a/README.md b/README.md index 7cc3e18..e57cfb6 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ - [5.2 Pin 动态二进制插桩](doc/5.2_pin.md) - [5.3 angr 二进制自动化分析](doc/5.3_angr.md) - [5.4 反调试技术](doc/5.4_antidbg.md) - - [5.5 Symbolic Execution 符号执行技术](doc/5.5_symbolic.md) + - [5.5 符号执行](doc/5.5_symbolic.md) - [5.6 LLVM](doc/5.6_llvm.md) - [六、附录](doc/6_appendix.md) diff --git a/SUMMARY.md b/SUMMARY.md index f6c0748..3aaab0a 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -50,7 +50,7 @@ * [5.2 Pin 动态二进制插桩](doc/5.2_pin.md) * [5.3 angr 二进制自动化分析](doc/5.3_angr.md) * [5.4 反调试技术](doc/5.4_antidbg.md) - * [5.5 Symbolic Execution 符号执行](doc/5.5_symbolic.md) + * [5.5 符号执行](doc/5.5_symbolic.md) * [5.6 LLVM](doc/5.6_llvm.md) * [六、附录](doc/6_appendix.md) * [6.1 更多 Linux 工具](doc/6.1_Linuxtools.md) diff --git a/doc/2.2_gdb&peda.md b/doc/2.2_gdb&peda.md index 9eda850..9a88996 100644 --- a/doc/2.2_gdb&peda.md +++ b/doc/2.2_gdb&peda.md @@ -203,6 +203,13 @@ long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data); PEDA(Python Exploit Development Assistance for GDB)是一个强大的 gdb 插件。它提供了高亮显示反汇编代码、寄存器、内存信息等人性化的功能。同时,PEDA 还有一些实用的新命令,比如 checksec 可以查看程序开启了哪些安全机制等等。 #### 安装 +安装 peda 需要的软件包: +```shell +$ sudo apt-get install nasm micro-inetd +$ sudo apt-get install libc6-dbg vim ssh +``` + +安装 peda: ```shell $ git clone https://github.com/longld/peda.git ~/peda $ echo "source ~/peda/peda.py" >> ~/.gdbinit @@ -217,84 +224,347 @@ $ yaourt -S peda #### peda命令 - **`aslr`** -- 显示/设置 gdb 的 ASLR - `asmsearch` -- Search for ASM instructions in memory + - `asmsearch "int 0x80"` + - `asmsearch "add esp, ?" libc` - `assemble` -- On the fly assemble and execute instructions using NASM + - `assemble` + - ``` + assemble $pc + > mov al, 0xb + > int 0x80 + > end + ``` - **`checksec`** -- 检查二进制文件的安全选项 - `cmpmem` -- Compare content of a memory region with a file + - `cmpmem 0x08049000 0x0804a000 data.mem` - `context` -- Display various information of current execution context -- `context_code` -- Display nearby disassembly at $PC of current execution context -- `context_register` -- Display register information of current execution context -- `context_stack` -- Display stack of current execution context + - `context_code` -- Display nearby disassembly at $PC of current execution context + - `context_register` -- Display register information of current execution context + - `context_stack` -- Display stack of current execution context + - `context reg` + - `context code` + - `context stack` - `crashdump` -- Display crashdump info and save to file - `deactive` -- Bypass a function by ignoring its execution (eg sleep/alarm) + - `deactive setresuid` + - `deactive chdir` - `distance` -- Calculate distance between two addresses - **`dumpargs`** -- 在调用指令停止时显示传递给函数的参数 - `dumpmem` -- Dump content of a memory region to raw binary file + - `dumpmem libc.mem libc` - **`dumprop`** -- 在特定的内存范围显示 ROP gadgets + - `dumprop` + - `dumprop binary "pop"` - `eflags` -- Display/set/clear/toggle value of eflags register - **`elfheader`** -- 获取正在调试的 ELF 文件的头信息 + - `elfheader` + - `elfheader .got` - **`elfsymbol`** -- 从 ELF 文件中获取没有调试信息的符号信息 + - `elfsymbol` + - `elfsymbol printf` - `gennop` -- Generate abitrary length NOP sled using given characters + - `gennop 500` + - `gennop 500 "\x90"` - `getfile` -- Get exec filename of current debugged process - `getpid` -- Get PID of current debugged process - `goto` -- Continue execution at an address - `help` -- Print the usage manual for PEDA commands - `hexdump` -- Display hex/ascii dump of data in memory + - `hexdump $sp 64` + - `hexdump $sp /20` - `hexprint` -- Display hexified of data in memory + - `hexprint $sp 64` + - `hexprint $sp /20` - `jmpcall` -- Search for JMP/CALL instructions in memory + - `jmpcall` + - `jmpcall eax` + - `jmpcall esp libc` - `loadmem` -- Load contents of a raw binary file to memory + - `loadmem stack.mem 0xbffdf000` - **`lookup`** -- 搜索属于内存范围的地址的所有地址/引用 + - `lookup address stack libc` + - `lookup pointer stack ld-2` - `nearpc` -- Disassemble instructions nearby current PC or given address + - `nearpc 20` + - `nearpc 0x08048484` - `nextcall` -- Step until next 'call' instruction in specific memory range + - `nextcall cpy` - `nextjmp` -- Step until next 'j*' instruction in specific memory range + - `nextjmp` - `nxtest` -- Perform real NX test to see if it is enabled/supported by OS - **`patch`** -- 使用字符串/十六进制字符串/整形数 + - `patch $esp 0xdeadbeef` + - `patch $eax "the long string"` + - `patch (multiple lines)` - **`pattern`** -- 生成,搜索或写入循环 pattern 到内存 -- `pattern_arg` -- Set argument list with cyclic pattern -- `pattern_create` -- Generate a cyclic pattern -- `pattern_env` -- Set environment variable with a cyclic pattern -- `pattern_offset` -- Search for offset of a value in cyclic pattern -- `pattern_patch` -- Write a cyclic pattern to memory -- `pattern_search` -- Search a cyclic pattern in registers and memory + - `pattern_arg` -- Set argument list with cyclic pattern + - `pattern_create` -- Generate a cyclic pattern + - `pattern_env` -- Set environment variable with a cyclic pattern + - `pattern_offset` -- Search for offset of a value in cyclic pattern + - `pattern_patch` -- Write a cyclic pattern to memory + - `pattern_search` -- Search a cyclic pattern in registers and memory + - `pattern create 2000` + - `pattern create 2000 input` + - `pattern offset $pc` + - `pattern search` + - `pattern patch 0xdeadbeef 100` - `payload` -- Generate various type of ROP payload using ret2plt + - `payload copybytes` + - `payload copybytes target "/bin/sh"` + - `payload copybytes 0x0804a010 offset` - `pdisass` -- Format output of gdb disassemble command with colors + - `pdisass $pc /20` - `pltbreak` -- Set breakpoint at PLT functions match name regex + - `pltbreak cpy` - **`procinfo`** -- 显示调试进程的 /proc/pid/ + - `procinfo` + - `procinfo fd` - `profile` -- Simple profiling to count executed instructions in the program - `pyhelp` -- Wrapper for python built-in help + - `pyhelp peda` + - `pyhelp hex2str` - **`pshow`** -- 显示各种 PEDA 选项和其他设置 + - `pshow` + - `pshow option context` - **`pset`** -- 设置各种 PEDA 选项和其他设置 + - `pset arg '"A"*200'` + - `pset arg 'cyclic_pattern(200)'` + - `pset env EGG 'cyclic_pattern(200)'` + - `pset option context "code,stack"` + - `pset option badchars "\r\n"` - **`readelf`** -- 获取 ELF 的文件头信息 + - `readelf libc .text` - `refsearch` -- Search for all references to a value in memory ranges + - `refsearch "/bin/sh"` + - `refsearch 0xdeadbeef` - `reload` -- Reload PEDA sources, keep current options untouch - **`ropgadget`** -- 获取二进制或库的常见 ROP gadgets + - `ropgadget` + - `ropgadget libc` - **`ropsearch`** -- 搜索内存中的 ROP gadgets + - `ropsearch "pop eax"` + - `ropsearch "xchg eax, esp" libc` - **`searchmem|find`** -- 搜索内存中的 pattern; 支持正则表达式搜索 + - `find "/bin/sh" libc` + - `find 0xdeadbeef all` + - `find "..\x04\x08" 0x08048000 0x08049000` - `searchmem` -- Search for a pattern in memory; support regex search - `session` -- Save/restore a working gdb session to file as a script - `set` -- Set various PEDA options and other settings + - `set exec-wrapper ./exploit.py` - `sgrep` -- Search for full strings contain the given pattern - **`shellcode`** -- 生成或下载常见的 shellcode + - `shellcode x86/linux exec` - `show` -- Show various PEDA options and other settings - **`skeleton`** -- 生成 python exploit 代码模板 + - `skeleton argv exploit.py` - `skipi` -- Skip execution of next count instructions - `snapshot` -- Save/restore process's snapshot to/from file + - `snapshot save` + - `snapshot restore` - `start` -- Start debugged program and stop at most convenient entry - `stepuntil` -- Step until a desired instruction in specific memory range + - `stepuntil cmp` + - `stepuntil xor` - `strings` -- Display printable strings in memory + - `strings` + - `strings binary 4` - `substr` -- Search for substrings of a given string/number in memory - `telescope` -- Display memory content at an address with smart dereferences + - `telescope 40` + - `telescope 0xb7d88000 40` - `tracecall` -- Trace function calls made by the program + - `tracecall` + - `tracecall "cpy,printf"` + - `tracecall "-puts,fflush"` - `traceinst` -- Trace specific instructions executed by the program + - `traceinst 20` + - `traceinst "cmp,xor"` - `unptrace` -- Disable anti-ptrace detection + - `unptrace` - `utils` -- Miscelaneous utilities from utils module - **`vmmap`** -- 在调试过程中获取段的虚拟映射地址范围 + - `cmmap` + - `vmmap binary / libc` + - `vmmap 0xb7d88000` - `waitfor` -- Try to attach to new forked process; mimic "attach -waitfor" + - `waitfor` + - `waitfor myprog -c` - `xinfo` -- Display detail information of address/registers + - `xinfo register eax` + - `xinfo 0xb7d88000` - **`xormem`** -- 用一个 key 来对一个内存区域执行 XOR 操作 + - `xormem 0x08049000 0x0804a000 “thekey”` - `xprint` -- Extra support to GDB's print command - `xrefs` -- Search for all call/data access references to a function/variable - `xuntil` -- Continue execution until an address or function +#### 使用 PEDA 和 Python 编写 gdb 脚本 +- 全局类 + - `pedacmd`: + - 交互式命令 + - 没有返回值 + - 例如:`pedacmd.context_register()` + - `peda`: + - 与 gdb 交互的后端功能 + - 有返回值 + - 例如:`peda.getreg("eax")` +- 小工具 + - 例如:`to_int()`、`format_address()` + - 获得帮助 + - `pyhelp peda` + - `pyhelp hex2str` +- 单行/交互式使用 + - `gdb-peda$ python print peda.get_vmmap()` + - ``` + gdb-peda$ python + > status = peda.get_status() + > while status == "BREAKPOINT": + > peda.execute("continue") + > end + ``` +- 外部脚本 + - ``` + # myscript.py + def myrun(size): + argv = cyclic_pattern(size) + peda.execute("set arg %s" % argv) + peda.execute("run") + ``` + ``` + gdb-peda$ source myscript.py + gdb-peda$ python myrun(100) + ``` + +下面我们通过一道 CTF 题目来练习一下 PEDA 脚本的编写:[asis-ctf-quals-2014 serial-number re-300](../src/Reverse/2.2_serial_number_300) +``` +__int64 __fastcall main(__int64 a1, char **a2, char **a3) +{ + __int64 result; // rax@5 + int v4; // ecx@9 + int v5; // ecx@9 + int v6; // ecx@9 + int v7; // ecx@9 + int v8; // ecx@9 + unsigned __int64 v9; // [sp+8h] [bp-68h]@4 + int v10; // [sp+10h] [bp-60h]@9 + int v11; // [sp+14h] [bp-5Ch]@9 + int v12; // [sp+18h] [bp-58h]@9 + int v13; // [sp+1Ch] [bp-54h]@9 + int v14; // [sp+20h] [bp-50h]@9 + int v15; // [sp+24h] [bp-4Ch]@9 + int v16; // [sp+28h] [bp-48h]@9 + int v17; // [sp+2Ch] [bp-44h]@9 + unsigned __int64 v18; // [sp+38h] [bp-38h]@6 + int v19; // [sp+44h] [bp-2Ch]@4 + _QWORD *v20; // [sp+48h] [bp-28h]@1 + int i; // [sp+54h] [bp-1Ch]@1 + int v22; // [sp+58h] [bp-18h]@1 + int v23; // [sp+5Ch] [bp-14h]@1 + + v23 = 0; + v22 = 1; + v20 = malloc(4uLL); + for ( i = 0; i <= 3; ++i ) + { + v20[i] = malloc(0xCuLL); + *(_DWORD *)(v20[i] + 8LL) = 1; + } + printf("Enter serial number in hex formet (without 0x prefix) : ", a2); + v19 = scanf("%llx", &v9); + if ( v19 > 0 ) + { + v18 = v9; + while ( v9 ) + { + v22 ^= 1u; + if ( *(_DWORD *)*v20 != v22 && v22 ) + { + v14 = v9 & 1; + v9 >>= 1; + v15 = v9 & 1; + v9 >>= 1; + v16 = v9 & 1; + v9 >>= 1; + v17 = v9 & 1; + v9 >>= 1; + v23 = *(_DWORD *)(v20[1] + 4LL) & (*(_DWORD *)(v20[2] + 4LL) == 0) & *(_BYTE *)(v20[3] + 4LL) & (unsigned __int8)v14 & (v15 == 0) & (unsigned __int8)(v16 & v17) & *(_DWORD *)(*v20 + 4LL); + v4 = *(_BYTE *)(v20[1] + 4LL) & (*(_DWORD *)(v20[2] + 4LL) == 0) & (unsigned __int8)(*(_BYTE *)(v20[3] + 4LL) & (v14 | (v15 == 0) | v16 | (v17 == 0))) & (*(_DWORD *)(*v20 + 4LL) == 0) | (*(_DWORD *)(v20[1] + 4LL) == 0) & (*(_DWORD *)(v20[2] + 4LL) == 0) & (unsigned __int8)(*(_BYTE *)(v20[3] + 4LL) & ((v14 == 0) | (v15 == 0) | v16 | v17)) & *(_DWORD *)(*v20 + 4LL) | (*(_DWORD *)(v20[1] + 4LL) == 0) & (*(_DWORD *)(v20[2] + 4LL) == 0) & (unsigned __int8)(*(_BYTE *)(v20[3] + 4LL) & (v14 | v15 | (v16 == 0) | v17)) & (*(_DWORD *)(*v20 + 4LL) == 0) | *(_DWORD *)(*v20 + 4LL) & *(_DWORD *)(v20[1] + 4LL) & *(_DWORD *)(v20[2] + 4LL) & (*(_DWORD *)(v20[3] + 4LL) == 0) & (v14 == 0) & (v15 == 0) & (unsigned __int8)(v16 & v17); + v13 = v4 | *(_DWORD *)(v20[1] + 4LL) & (*(_DWORD *)(v20[2] + 4LL) == 0) & *(_DWORD *)(v20[3] + 4LL) & *(_DWORD *)(*v20 + 4LL); + v5 = *(_BYTE *)(v20[1] + 4LL) & *(_BYTE *)(v20[2] + 4LL) & (*(_DWORD *)(v20[3] + 4LL) == 0) & (unsigned __int8)((v14 == 0) | v15 | (v16 == 0) | v17) & (*(_DWORD *)(*v20 + 4LL) == 0) | (*(_DWORD *)(v20[1] + 4LL) == 0) & *(_BYTE *)(v20[2] + 4LL) & (*(_DWORD *)(v20[3] + 4LL) == 0) & (unsigned __int8)(v14 | (v15 == 0) | v16 | v17) & *(_DWORD *)(*v20 + 4LL) | (*(_DWORD *)(v20[1] + 4LL) == 0) & *(_BYTE *)(v20[2] + 4LL) & (*(_DWORD *)(v20[3] + 4LL) == 0) & (unsigned __int8)((v14 == 0) | v15 | v16 | v17) & (*(_DWORD *)(*v20 + 4LL) == 0) | *(_DWORD *)(*v20 + 4LL) & *(_DWORD *)(v20[1] + 4LL) & (*(_DWORD *)(v20[2] + 4LL) == 0) & (*(_DWORD *)(v20[3] + 4LL) == 0) & (unsigned __int8)v14 & (unsigned __int8)v15 & (unsigned __int8)v16 & (v17 == 0); + v12 = v5 | *(_DWORD *)(v20[1] + 4LL) & *(_DWORD *)(v20[2] + 4LL) & (*(_DWORD *)(v20[3] + 4LL) == 0) & *(_DWORD *)(*v20 + 4LL); + v6 = (*(_DWORD *)(v20[1] + 4LL) == 0) & *(_BYTE *)(v20[2] + 4LL) & (*(_DWORD *)(v20[3] + 4LL) == 0) & (v14 == 0) & (unsigned __int8)v15 & (v17 == 0 && v16 == 0) & *(_DWORD *)(*v20 + 4LL) | *(_DWORD *)(v20[1] + 4LL) & (*(_DWORD *)(v20[3] + 4LL) == 0 && *(_DWORD *)(v20[2] + 4LL) == 0) & *(_DWORD *)(*v20 + 4LL) | *(_BYTE *)(v20[1] + 4LL) & (*(_DWORD *)(v20[2] + 4LL) == 0 && *(_DWORD *)(v20[3] + 4LL) == 0 && (v14 == 0 || v15 == 0 || v17 == 0 || v16 == 0)) & (*(_DWORD *)(*v20 + 4LL) == 0) | *(_DWORD *)(*v20 + 4LL) & (*(_DWORD *)(v20[1] + 4LL) == 0) & (*(_DWORD *)(v20[2] + 4LL) == 0) & (*(_DWORD *)(v20[3] + 4LL) == 0) & (unsigned __int8)v14 & (v15 == 0) & (v16 == 0) & (unsigned __int8)v17; + v11 = *(_BYTE *)(v20[1] + 4LL) & (*(_DWORD *)(v20[2] + 4LL) == 0) & (unsigned __int8)(*(_BYTE *)(v20[3] + 4LL) & (v14 | (v15 == 0) | v16 | (v17 == 0))) & (*(_DWORD *)(*v20 + 4LL) == 0) | (*(_DWORD *)(v20[1] + 4LL) == 0) & (*(_DWORD *)(v20[2] + 4LL) == 0) & *(_BYTE *)(v20[3] + 4LL) & (unsigned __int8)v14 & (unsigned __int8)v15 & (v17 == 0 && v16 == 0) & *(_DWORD *)(*v20 + 4LL) | *(_DWORD *)(v20[1] + 4LL) & *(_DWORD *)(v20[2] + 4LL) & (*(_DWORD *)(v20[3] + 4LL) == 0) & *(_DWORD *)(*v20 + 4LL) | *(_BYTE *)(v20[1] + 4LL) & *(_BYTE *)(v20[2] + 4LL) & (*(_DWORD *)(v20[3] + 4LL) == 0) & (unsigned __int8)((v14 == 0) | v15 | (v16 == 0) | v17) & (*(_DWORD *)(*v20 + 4LL) == 0) | v6 | *(_DWORD *)(v20[1] + 4LL) & (*(_DWORD *)(v20[2] + 4LL) == 0) & *(_DWORD *)(v20[3] + 4LL) & *(_DWORD *)(*v20 + 4LL); + v7 = *(_DWORD *)(v20[1] + 4LL) & (*(_DWORD *)(v20[3] + 4LL) == 0 && *(_DWORD *)(v20[2] + 4LL) == 0) & *(_DWORD *)(*v20 + 4LL) | *(_BYTE *)(v20[1] + 4LL) & (*(_DWORD *)(v20[2] + 4LL) == 0) & (*(_DWORD *)(v20[3] + 4LL) == 0) & (unsigned __int8)(v14 & v15 & v16 & v17) & (*(_DWORD *)(*v20 + 4LL) == 0) | (*(_DWORD *)(v20[1] + 4LL) == 0 && *(_DWORD *)(v20[3] + 4LL) == 0 && *(_DWORD *)(v20[2] + 4LL) == 0) & *(_DWORD *)(*v20 + 4LL) | (*(_DWORD *)(*v20 + 4LL) == 0) & (*(_DWORD *)(v20[1] + 4LL) == 0) & (*(_DWORD *)(v20[2] + 4LL) == 0) & (*(_DWORD *)(v20[3] + 4LL) == 0) & (unsigned __int8)v14 & (v15 == 0) & (unsigned __int8)(v16 & v17); + v8 = *(_DWORD *)(v20[1] + 4LL) & *(_DWORD *)(v20[2] + 4LL) & (*(_DWORD *)(v20[3] + 4LL) == 0) & *(_DWORD *)(*v20 + 4LL) | *(_BYTE *)(v20[1] + 4LL) & *(_BYTE *)(v20[2] + 4LL) & (*(_DWORD *)(v20[3] + 4LL) == 0) & (unsigned __int8)v14 & (v15 == 0) & (unsigned __int8)v16 & (v17 == 0) & (*(_DWORD *)(*v20 + 4LL) == 0) | (*(_DWORD *)(v20[1] + 4LL) == 0) & *(_BYTE *)(v20[2] + 4LL) & (*(_DWORD *)(v20[3] + 4LL) == 0) & *(_DWORD *)(*v20 + 4LL) | (*(_DWORD *)(v20[1] + 4LL) == 0) & *(_BYTE *)(v20[2] + 4LL) & (*(_DWORD *)(v20[3] + 4LL) == 0) & (unsigned __int8)v14 & (v15 == 0 && v17 == 0 && v16 == 0) & (*(_DWORD *)(*v20 + 4LL) == 0) | v7; + v10 = *(_BYTE *)(v20[1] + 4LL) & (*(_DWORD *)(v20[2] + 4LL) == 0) & *(_BYTE *)(v20[3] + 4LL) & (v14 == 0) & (unsigned __int8)v15 & (v16 == 0) & (unsigned __int8)v17 & (*(_DWORD *)(*v20 + 4LL) == 0) | (*(_DWORD *)(v20[1] + 4LL) == 0) & (*(_DWORD *)(v20[2] + 4LL) == 0) & *(_BYTE *)(v20[3] + 4LL) & *(_DWORD *)(*v20 + 4LL) | (*(_DWORD *)(v20[1] + 4LL) == 0) & (*(_DWORD *)(v20[2] + 4LL) == 0) & *(_BYTE *)(v20[3] + 4LL) & (v14 == 0) & (v15 == 0) & (unsigned __int8)v16 & (v17 == 0) & (*(_DWORD *)(*v20 + 4LL) == 0) | v8 | *(_DWORD *)(v20[1] + 4LL) & (*(_DWORD *)(v20[2] + 4LL) == 0) & *(_DWORD *)(v20[3] + 4LL) & *(_DWORD *)(*v20 + 4LL); + sub_40064D((unsigned int)v13, v20[3]); + sub_40064D((unsigned int)v12, v20[2]); + sub_40064D((unsigned int)v11, v20[1]); + sub_40064D((unsigned int)v10, *v20); + } + *(_DWORD *)v20[3] = v22; + *(_DWORD *)v20[2] = v22; + *(_DWORD *)v20[1] = v22; + *(_DWORD *)*v20 = v22; + } + if ( v23 == 1 ) + printf("\nCongratulation! Send \"ASIS_MD5(%llx)\" as the flag!", v18); + else + printf("Sorry! The serial number is incorrect!"); + result = 0LL; + } + else + { + printf("Invalid number."); + result = 0LL; + } + return result; +} +``` +上面是在 IDA Pro 中 F5 的结果,可以看到程序中有非常长的位操作逻辑,如果硬着头皮分析的话会非常困难。下面我们借用 PEDA 强大的能力来解决它,首先简化下上面的代码: +``` +int v9; // serial_number +int v23; // correct_serial + +v23 = 0; + +while (v9) { + v14 = v9 & 1; + v9 >>= 1; + v15 = v9 & 1; + v9 >>= 1; + v16 = v9 & 1; + v9 >>= 1; + v17 = v9 & 1; + v9 >>= 1; + v23 = v23 = *(_DWORD *)(v20[1] + 4LL) & (*(_DWORD *)(v20[2] + 4LL) == 0) & *(_BYTE *)(v20[3] + 4LL) & (unsigned __int8)v14 & (v15 == 0) & (unsigned __int8)(v16 & v17) & *(_DWORD *)(*v20 + 4LL); + (v20, v20[1], v20[2], v20[3]) = very_long_bit_operation_asm((v20, v20[1], v20[2], v20[3]), (v14, v15, v16, v17)); +} + +if (v23 == 1) { + printf("Congratulation!"); +} +``` +大概就是这样,我们用 `very_long_bit_operation_asm()` 函数代替了近千行的位操作,它的参数可以分为两组,`(v20, v20[1], v20[2], v20[3])` 和 `(v14, v15, v16, v17)`,每个组表示 4 比特的变量。所以,无论这个函数是什么操作,都只有 `16 * 16 = 256` 种可能,我们就可以使用暴力的方式破解它。 + +通过设置 `rip` 为循环代码的开始,并在 `` 函数结束处设置断点,我们就可以使代码循环执行了。 +```text +0000000000400768 loc_400768: ; CODE XREF: main+E43 +... +.text:0000000000400788 mov rax, [rbp+var_68] +... +000000000040149C +.text:000000000040149C loc_40149C: ; CODE XREF: main+DC +.text:000000000040149C ; main+E6 +... +00000000004014D8 +.text:00000000004014D8 loc_4014D8: ; CODE XREF: main+C7 +.text:00000000004014D8 mov rax, [rbp+var_68] +``` + +参考 http://blog.ztrix.me/blog/2014/05/10/asis-quals-2014-serial-number-writeup/ + #### 更多资料 http://ropshell.com/peda/ diff --git a/doc/5.1_fuzz.md b/doc/5.1_fuzz.md index 0ebbd21..8770079 100644 --- a/doc/5.1_fuzz.md +++ b/doc/5.1_fuzz.md @@ -1 +1,6 @@ # Fuzz 测试 + +- [AFL](#afl) + + +## AFL diff --git a/doc/5.5_symbolic.md b/doc/5.5_symbolic.md index c4624c9..bedbf18 100644 --- a/doc/5.5_symbolic.md +++ b/doc/5.5_symbolic.md @@ -1,7 +1,8 @@ -# Symbolic Execution 符号执行技术 +# 5.5 符号执行 + +- [符号执行的历史](#符号执行的历史) +- [什么是符号执行](#什么是符号执行) -* [符号执行的历史](#符号执行的历史) -* [什么是符号执行](#什么是符号执行) ## 符号执行的历史 @@ -10,8 +11,4 @@ 或者进入[https://github.com/enzet/symbolic-execution](https://github.com/enzet/symbolic-execution)查看SVG大图。 - ## 什么是符号执行 - - - diff --git a/src/Reverse/2.2_serial_number_300 b/src/Reverse/2.2_serial_number_300 new file mode 100755 index 0000000..101f014 Binary files /dev/null and b/src/Reverse/2.2_serial_number_300 differ