mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2025-01-27 05:57:33 +07:00
fix
This commit is contained in:
parent
f34cb95061
commit
070603e235
@ -170,6 +170,7 @@ GitHub 地址:https://github.com/firmianay/CTF-All-In-One
|
||||
* [6.2.5 re PicoCTF2014 Baleful](doc/6.2.5_re_picoctf2014_baleful.md)
|
||||
* [6.2.6 re SECCONCTF2017 printf_machine](doc/6.2.6_re_secconctf2017_printf_machine.md)
|
||||
* [6.2.7 re CodegateCTF2018 RedVelvet](doc/6.2.7_re_codegatectf2018_redvelvet.md)
|
||||
* [6.2.8 re DefcampCTF2015 entry_language](doc/6.2.8_re_defcampctf2015_entry_language.md)
|
||||
* Web
|
||||
* [6.3.1 web HCTF2017 babycrack](doc/6.3.1_web_hctf2017_babycrack.md)
|
||||
* Crypto
|
||||
@ -212,6 +213,7 @@ GitHub 地址:https://github.com/firmianay/CTF-All-In-One
|
||||
* [8.22 Practical Memory Checking With Dr. Memory](doc/8.22_memory_checking.md)
|
||||
* [8.23 Evaluating the Effectiveness of Current Anti-ROP Defenses](doc/8.23_current_anti-rop.md)
|
||||
* [8.24 How to Make ASLR Win the Clone Wars: Runtime Re-Randomization](doc/8.24_runtime_re-randomization.md)
|
||||
* [8.25 (State of) The Art of War: Offensive Techniques in Binary Analysis](doc/8.25_offsensive_techniques.md)
|
||||
* [九、附录](doc/9_appendix.md)
|
||||
* [9.1 更多 Linux 工具](doc/9.1_Linuxtools.md)
|
||||
* [9.2 更多 Windows 工具](doc/9.2_wintools.md)
|
||||
|
@ -203,7 +203,7 @@ node hello.js
|
||||
```
|
||||
来执行文件。
|
||||
|
||||
![](../pic/1.4.3_nodejs)
|
||||
![](../pic/1.4.3_nodejs.png)
|
||||
|
||||
|
||||
## Node.js 模块
|
||||
|
@ -9,11 +9,14 @@
|
||||
- F2:在光标选定位置按 F2 键设置或取消断点。
|
||||
- F4:运行到光标选定位置处暂停。
|
||||
- F7:单步步入:每次执行一条指令,遇到 call 等子程序时进入其中。
|
||||
- Shift+F7:与 F7 相同,但当调试程序发生异常而中止时,调试器首先尝试步入
|
||||
- F8:单步步过,每次执行一条指令,遇到 call 等子程序时不进入其中。
|
||||
- F9:运行,被调试软件继续运行,直到遇到下一个断点。
|
||||
- Ctrl+F2:重新启动被调试程序。
|
||||
- Ctrl+F9:执行到返回,在执行到一个 ret 指令时暂停,常用于从当前函数快速返回到上一个函数。
|
||||
- Alt+F9:执行到用户代码,可用于从系统部分快速返回到被调试程序部分。
|
||||
- Ctrl+G:查看任意地址的数据。
|
||||
- Alt+F9:执行到用户代码,可用于从系统部分快速返回到被调试程序部分。
|
||||
- Alt+F5:让 OllyDbg 窗口总在最前面。
|
||||
|
||||
|
||||
## 命令行插件
|
||||
|
@ -821,12 +821,12 @@ p4: 0x1e2b0a0 ~ 0x1e2b8e0
|
||||
p3: 0x1e2b130 ~ 0x1e2b530
|
||||
|
||||
If we memset(p4, 'B', 0xd0), we have:
|
||||
p4 = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
|
||||
p3 = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
|
||||
p4 = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
|
||||
p3 = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
|
||||
|
||||
If we memset(p3, 'C', 0x50), we have:
|
||||
p4 = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
|
||||
p3 = CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
|
||||
p4 = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
|
||||
p3 = CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa
|
||||
```
|
||||
这个比较简单,就是堆块重叠的问题。通过一个溢出漏洞,改写 unsorted bin 中空闲堆块的 size,改变下一次 malloc 可以返回的堆块大小。
|
||||
|
||||
|
@ -50,7 +50,7 @@ blx r5
|
||||
|
||||
由于 update-load-branch 指令序列相比 return 指令更加稀少,所以需要把它作为 trampoline 重复利用。在构造 ROP 链时,选择以 trampoline 为目标的间接跳转指令结束的指令序列。当一个 gadget 执行结束后,跳转到 trampoline,trampoline 更新程序全局状态,并将程序控制交给下一个 gadget,这样就形成了 ROP 链。
|
||||
|
||||
![](../pic/8.1.2_rop_without_ret.png)
|
||||
![](../pic/8.2_rop_without_ret.png)
|
||||
|
||||
|
||||
## 参考资料
|
||||
|
@ -1 +1,25 @@
|
||||
# 5.2.3 Valgrind
|
||||
|
||||
- [简介](#简介)
|
||||
- [使用方法](#使用方法)
|
||||
- [VEX IR](#vex-ir)
|
||||
- [参考资料](#参考资料)
|
||||
|
||||
|
||||
## 简介
|
||||
Valgrind 是一个用于内存调试、内存泄漏检测以及性能分析的动态二进制插桩工具。Valgrind 由 core 以及基于 core 的其他调试工具组成。core 类似于一个框架,它模拟了一个 CPU 环境,并提供服务给其他工具,而其他工具以插件的形式利用 core 提供的服务完成各种特定的任务。
|
||||
|
||||
|
||||
## 使用方法
|
||||
|
||||
|
||||
## VEX IR
|
||||
VEX IR 是 Valgrind 所使用的中间表示,供 DBI 使用,后来这一部分被分离出去作为 libVEX,libVEX 负责将机器码转换成 VEX IR,转换结果存放在 cache 中。
|
||||
|
||||
顺便,再简单提一下其他的类似用途的 IR 还有:BAP、REIL、LLVM、TCG 等。
|
||||
|
||||
|
||||
## 参考资料
|
||||
- [Valgrind: A Framework for Heavyweight Dynamic Binary Instrumentation](http://valgrind.org/docs/valgrind2007.pdf)
|
||||
- [Optimizing Binary Code Produced by Valgrind](https://pdfs.semanticscholar.org/6761/acf36975d38fd5f616cb4798bfa3a92cbfa3.pdf)
|
||||
- [libvex_ir.h](https://github.com/angr/vex/blob/dev/pub/libvex_ir.h)
|
||||
|
@ -1,13 +1,18 @@
|
||||
# 5.3.1 angr
|
||||
|
||||
- [简介](#简介)
|
||||
- [安装](#安装)
|
||||
- [使用 angr](#使用-angr)
|
||||
- [入门](#入门)
|
||||
- [加载二进制文件](#加载二进制文件)
|
||||
- [angr 在 CTF 中的运用](#angr-在-ctf-中的运用)
|
||||
- [使用方法](#使用方法)
|
||||
- [快速入门](#快速入门)
|
||||
- [二进制文件加载器](#二进制文件加载器)
|
||||
- [求解器引擎](#求解器引擎)
|
||||
- [VEX IR 翻译器](#vex-ir-翻译)
|
||||
- [体系结构信息收集](#体系结构信息收集)
|
||||
- [CTF 实例](#ctf-实例)
|
||||
- [参考资料](#参考资料)
|
||||
|
||||
|
||||
## 简介
|
||||
[angr](https://github.com/angr/angr) 是一个多架构的二进制分析平台,具备对二进制文件的动态符号执行能力和多种静态分析能力。在近几年的 CTF 中也大有用途。
|
||||
|
||||
|
||||
@ -29,7 +34,7 @@ $ sudo apt install python-dev libffi-dev build-essential virtualenvwrapper
|
||||
4. cle
|
||||
5. angr
|
||||
```
|
||||
如:
|
||||
例如下面这样:
|
||||
```shell
|
||||
$ git clone https://github.com/angr/claripy
|
||||
$ cd claripy
|
||||
@ -37,13 +42,11 @@ $ sudo pip install -r requirements.txt
|
||||
$ sudo python setup.py build
|
||||
$ sudo python setup.py install
|
||||
```
|
||||
其他几个库也是一样的。
|
||||
|
||||
安装过程中可能会有一些奇怪的错误,可以到官方文档中查看。
|
||||
|
||||
|
||||
## 使用 angr
|
||||
#### 入门
|
||||
## 使用方法
|
||||
#### 快速入门
|
||||
使用 angr 的第一步是新建一个工程,几乎所有的操作都是围绕这个工程展开的:
|
||||
```python
|
||||
>>> import angr
|
||||
@ -111,7 +114,7 @@ WARNING | 2017-12-08 11:09:28,629 | cle.loader | The main binary is a position-i
|
||||
>>> block.capstone
|
||||
<CapstoneBlock for 0x4013b0>
|
||||
>>> block.capstone.pp()
|
||||
>>>
|
||||
|
||||
>>> block.vex
|
||||
<pyvex.block.IRSB object at 0x7fe526b98670>
|
||||
>>> block.vex.pp()
|
||||
@ -201,7 +204,7 @@ WARNING | 2017-12-08 11:09:28,629 | cle.loader | The main binary is a position-i
|
||||
```
|
||||
|
||||
#### 加载二进制文件
|
||||
angr 的二进制加载模块称为 CLE。主类为 `cle.loader.Loader`,它导入所有的对象文件并导出一个进程内存的抽象。类 `cle.backends` 是加载器的后端,根据二进制文件类型区分为 `cle.backends.elf`、`cle.backends.pe`、`cle.backends.macho` 等。
|
||||
我们知道 angr 是高度模块化的,接下来我们就分别来看看这些组成模块,其中用于二进制加载模块称为 CLE。主类为 `cle.loader.Loader`,它导入所有的对象文件并导出一个进程内存的抽象。类 `cle.backends` 是加载器的后端,根据二进制文件类型区分为 `cle.backends.elf`、`cle.backends.pe`、`cle.backends.macho` 等。
|
||||
|
||||
加载对象文件和细分类型如下:
|
||||
```python
|
||||
@ -234,184 +237,63 @@ angr 的二进制加载模块称为 CLE。主类为 `cle.loader.Loader`,它导
|
||||
<.text | offset 0x12f0, vaddr 0x4012f0, size 0x33c9>
|
||||
```
|
||||
|
||||
#### 求解器引擎
|
||||
|
||||
## angr 在 CTF 中的运用
|
||||
#### re DefcampCTF2015 entry_language
|
||||
这是一题标准的密码验证题,输入一个字符串,程序验证对误。
|
||||
```
|
||||
$ file entry_language
|
||||
defcamp_r100: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=0f464824cc8ee321ef9a80a799c70b1b6aec8168, stripped
|
||||
```
|
||||
```
|
||||
$ ./entry_language
|
||||
Enter the password: ABCD
|
||||
Incorrect password!
|
||||
```
|
||||
#### VEX IR 翻译器
|
||||
angr 使用了 VEX 作为二进制分析的中间表示。VEX IR 是由 Valgrind 项目开发和使用的中间表示,后来这一部分被分离出去作为 libVEX,libVEX 用于将机器码转换成 VEX IR(更多内容参考章节5.2.3)。在 angr 项目中,开发了模块 [PyVEX](https://github.com/angr/pyvex) 作为 libVEX 的 Python 包装。当然也对 libVEX 做了一些修改,使其更加适用于程序分析。
|
||||
|
||||
为了与 angr 的自动化做对比,我们先使用传统的方法,逆向算法求解,`main` 函数和验证函数 `fcn.004006fd` 如下:
|
||||
```
|
||||
[0x00400610]> pdf @ main
|
||||
/ (fcn) main 153
|
||||
| main ();
|
||||
| ; var int local_110h @ rbp-0x110
|
||||
| ; var int local_8h @ rbp-0x8
|
||||
| ; DATA XREF from 0x0040062d (entry0)
|
||||
| 0x004007e8 55 push rbp
|
||||
| 0x004007e9 4889e5 mov rbp, rsp
|
||||
| 0x004007ec 4881ec100100. sub rsp, 0x110
|
||||
| 0x004007f3 64488b042528. mov rax, qword fs:[0x28] ; [0x28:8]=-1 ; '(' ; 40
|
||||
| 0x004007fc 488945f8 mov qword [local_8h], rax
|
||||
| 0x00400800 31c0 xor eax, eax
|
||||
| 0x00400802 bf37094000 mov edi, str.Enter_the_password: ; 0x400937 ; "Enter the password: "
|
||||
| 0x00400807 b800000000 mov eax, 0
|
||||
| 0x0040080c e8affdffff call sym.imp.printf ; int printf(const char *format)
|
||||
| 0x00400811 488b15500820. mov rdx, qword [obj.stdin] ; [0x601068:8]=0
|
||||
| 0x00400818 488d85f0feff. lea rax, [local_110h]
|
||||
| 0x0040081f beff000000 mov esi, 0xff ; 255
|
||||
| 0x00400824 4889c7 mov rdi, rax
|
||||
| 0x00400827 e8b4fdffff call sym.imp.fgets ; char *fgets(char *s, int size, FILE *stream)
|
||||
| 0x0040082c 4885c0 test rax, rax
|
||||
| ,=< 0x0040082f 7435 je 0x400866
|
||||
| | 0x00400831 488d85f0feff. lea rax, [local_110h]
|
||||
| | 0x00400838 4889c7 mov rdi, rax
|
||||
| | 0x0040083b e8bdfeffff call fcn.004006fd ; 调用验证函数
|
||||
| | 0x00400840 85c0 test eax, eax
|
||||
| ,==< 0x00400842 7511 jne 0x400855
|
||||
| || 0x00400844 bf4c094000 mov edi, str.Nice_ ; 0x40094c ; "Nice!"
|
||||
| || 0x00400849 e852fdffff call sym.imp.puts ; int puts(const char *s)
|
||||
| || 0x0040084e b800000000 mov eax, 0
|
||||
| ,===< 0x00400853 eb16 jmp 0x40086b
|
||||
| ||| ; JMP XREF from 0x00400842 (main)
|
||||
| |`--> 0x00400855 bf52094000 mov edi, str.Incorrect_password_ ; 0x400952 ; "Incorrect password!"
|
||||
| | | 0x0040085a e841fdffff call sym.imp.puts ; int puts(const char *s)
|
||||
| | | 0x0040085f b801000000 mov eax, 1
|
||||
| |,==< 0x00400864 eb05 jmp 0x40086b
|
||||
| ||| ; JMP XREF from 0x0040082f (main)
|
||||
| ||`-> 0x00400866 b800000000 mov eax, 0
|
||||
| || ; JMP XREF from 0x00400864 (main)
|
||||
| || ; JMP XREF from 0x00400853 (main)
|
||||
| ``--> 0x0040086b 488b4df8 mov rcx, qword [local_8h]
|
||||
| 0x0040086f 6448330c2528. xor rcx, qword fs:[0x28]
|
||||
| ,=< 0x00400878 7405 je 0x40087f
|
||||
| | 0x0040087a e831fdffff call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
|
||||
| | ; JMP XREF from 0x00400878 (main)
|
||||
| `-> 0x0040087f c9 leave
|
||||
\ 0x00400880 c3 ret
|
||||
[0x00400610]> pdf @ fcn.004006fd
|
||||
/ (fcn) fcn.004006fd 171
|
||||
| fcn.004006fd (int arg_bh);
|
||||
| ; var int local_38h @ rbp-0x38
|
||||
| ; var int local_24h @ rbp-0x24
|
||||
| ; var int local_20h @ rbp-0x20
|
||||
| ; var int local_18h @ rbp-0x18
|
||||
| ; var int local_10h @ rbp-0x10
|
||||
| ; arg int arg_bh @ rbp+0xb
|
||||
| ; CALL XREF from 0x0040083b (main)
|
||||
| 0x004006fd 55 push rbp
|
||||
| 0x004006fe 4889e5 mov rbp, rsp
|
||||
| 0x00400701 48897dc8 mov qword [local_38h], rdi
|
||||
| 0x00400705 c745dc000000. mov dword [local_24h], 0
|
||||
| 0x0040070c 48c745e01409. mov qword [local_20h], str.Dufhbmf ; 0x400914 ; "Dufhbmf"
|
||||
| 0x00400714 48c745e81c09. mov qword [local_18h], str.pG_imos ; 0x40091c ; "pG`imos"
|
||||
| 0x0040071c 48c745f02409. mov qword [local_10h], str.ewUglpt ; 0x400924 ; "ewUglpt"
|
||||
| 0x00400724 c745dc000000. mov dword [local_24h], 0
|
||||
| ,=< 0x0040072b eb6e jmp 0x40079b
|
||||
| | ; JMP XREF from 0x0040079f (fcn.004006fd)
|
||||
| .--> 0x0040072d 8b4ddc mov ecx, dword [local_24h]
|
||||
| :| 0x00400730 ba56555555 mov edx, 0x55555556
|
||||
| :| 0x00400735 89c8 mov eax, ecx
|
||||
| :| 0x00400737 f7ea imul edx
|
||||
| :| 0x00400739 89c8 mov eax, ecx
|
||||
| :| 0x0040073b c1f81f sar eax, 0x1f
|
||||
| :| 0x0040073e 29c2 sub edx, eax
|
||||
| :| 0x00400740 89d0 mov eax, edx
|
||||
| :| 0x00400742 01c0 add eax, eax
|
||||
| :| 0x00400744 01d0 add eax, edx
|
||||
| :| 0x00400746 29c1 sub ecx, eax
|
||||
| :| 0x00400748 89ca mov edx, ecx
|
||||
| :| 0x0040074a 4863c2 movsxd rax, edx
|
||||
| :| 0x0040074d 488b74c5e0 mov rsi, qword [rbp + rax*8 - 0x20]
|
||||
| :| 0x00400752 8b4ddc mov ecx, dword [local_24h]
|
||||
| :| 0x00400755 ba56555555 mov edx, 0x55555556
|
||||
| :| 0x0040075a 89c8 mov eax, ecx
|
||||
| :| 0x0040075c f7ea imul edx
|
||||
| :| 0x0040075e 89c8 mov eax, ecx
|
||||
| :| 0x00400760 c1f81f sar eax, 0x1f
|
||||
| :| 0x00400763 29c2 sub edx, eax
|
||||
| :| 0x00400765 89d0 mov eax, edx
|
||||
| :| 0x00400767 01c0 add eax, eax
|
||||
| :| 0x00400769 4898 cdqe
|
||||
| :| 0x0040076b 4801f0 add rax, rsi ; '+'
|
||||
| :| 0x0040076e 0fb600 movzx eax, byte [rax]
|
||||
| :| 0x00400771 0fbed0 movsx edx, al
|
||||
| :| 0x00400774 8b45dc mov eax, dword [local_24h]
|
||||
| :| 0x00400777 4863c8 movsxd rcx, eax
|
||||
| :| 0x0040077a 488b45c8 mov rax, qword [local_38h]
|
||||
| :| 0x0040077e 4801c8 add rax, rcx ; '&'
|
||||
| :| 0x00400781 0fb600 movzx eax, byte [rax]
|
||||
| :| 0x00400784 0fbec0 movsx eax, al
|
||||
| :| 0x00400787 29c2 sub edx, eax
|
||||
| :| 0x00400789 89d0 mov eax, edx
|
||||
| :| 0x0040078b 83f801 cmp eax, 1 ; 1
|
||||
| ,===< 0x0040078e 7407 je 0x400797 ; = 1 时跳转,验证成功
|
||||
| |:| 0x00400790 b801000000 mov eax, 1 ; 返回 1,验证失败
|
||||
| ,====< 0x00400795 eb0f jmp 0x4007a6
|
||||
| ||:| ; JMP XREF from 0x0040078e (fcn.004006fd)
|
||||
| |`---> 0x00400797 8345dc01 add dword [local_24h], 1 ; i = i + 1
|
||||
| | :| ; JMP XREF from 0x0040072b (fcn.004006fd)
|
||||
| | :`-> 0x0040079b 837ddc0b cmp dword [local_24h], 0xb ; [0xb:4]=-1 ; 11
|
||||
| | `==< 0x0040079f 7e8c jle 0x40072d ; i <= 11 时跳转
|
||||
| | 0x004007a1 b800000000 mov eax, 0 ; 返回 0
|
||||
| | ; JMP XREF from 0x00400795 (fcn.004006fd)
|
||||
| `----> 0x004007a6 5d pop rbp
|
||||
\ 0x004007a7 c3 ret
|
||||
```
|
||||
一些用法如下:
|
||||
```python
|
||||
>>> import pyvex, archinfo
|
||||
>>> bb = pyvex.IRSB('\xc3', 0x400400, archinfo.ArchAMD64()) # 将一个位于 0x400400 的 AMD64 基本块(\xc3,即ret)转成 VEX
|
||||
>>> bb.pp() # 打印
|
||||
IRSB {
|
||||
t0:Ity_I64 t1:Ity_I64 t2:Ity_I64 t3:Ity_I64
|
||||
|
||||
整理后可以得到下面的伪代码:
|
||||
```C
|
||||
int fcn_004006fd(int *passwd) {
|
||||
char *str_1 = "Dufhbmf";
|
||||
char *str_2 = "pG`imos";
|
||||
char *str_3 = "ewUglpt";
|
||||
for (int i = 0; i <= 11; i++) {
|
||||
if((&str_3)[i % 3][2 * (1 / 3)] - *(i + passwd) != 1) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
00 | ------ IMark(0x400400, 1, 0) ------
|
||||
01 | t0 = GET:I64(rsp)
|
||||
02 | t1 = LDle:I64(t0)
|
||||
03 | t2 = Add64(t0,0x0000000000000008)
|
||||
04 | PUT(rsp) = t2
|
||||
05 | t3 = Sub64(t2,0x0000000000000080)
|
||||
06 | ====== AbiHint(0xt3, 128, t1) ======
|
||||
NEXT: PUT(rip) = t1; Ijk_Ret
|
||||
}
|
||||
```
|
||||
然后写出逆向脚本:
|
||||
```python
|
||||
str_list = ["Dufhbmf", "pG`imos", "ewUglpt"]
|
||||
passwd = []
|
||||
for i in range(12):
|
||||
passwd.append(chr(ord(str_list[i % 3][2 * (i / 3)]) - 1))
|
||||
print ''.join(passwd)
|
||||
|
||||
>>> bb.statements[3] # 表达式
|
||||
<pyvex.stmt.WrTmp object at 0x7f38f1ef84b0>
|
||||
>>> bb.statements[3].pp()
|
||||
t2 = Add64(t0,0x0000000000000008)
|
||||
|
||||
>>> bb.statements[3].data # 数据
|
||||
<pyvex.expr.Binop object at 0x7f38f1ef8460>
|
||||
>>> bb.statements[3].data.pp()
|
||||
Add64(t0,0x0000000000000008)
|
||||
|
||||
>>> bb.statements[3].data.op # 操作符
|
||||
'Iop_Add64'
|
||||
|
||||
>>> bb.statements[3].data.args # 参数
|
||||
[<pyvex.expr.RdTmp object at 0x7f38f1f77cb0>, <pyvex.expr.Const object at 0x7f38f1f77098>]
|
||||
>>> bb.statements[3].data.args[0]
|
||||
<pyvex.expr.RdTmp object at 0x7f38f1f77cb0>
|
||||
>>> bb.statements[3].data.args[0].pp()
|
||||
t0
|
||||
|
||||
>>> bb.next # 基本块末尾无条件跳转的目标
|
||||
<pyvex.expr.RdTmp object at 0x7f38f3cb6f38>
|
||||
>>> bb.next.pp()
|
||||
t1
|
||||
|
||||
>>> bb.jumpkind # 无条件跳转的类型
|
||||
'Ijk_Ret'
|
||||
```
|
||||
|
||||
逆向算法似乎也很简单,但如果连算法都不用逆的话,下面就是见证 angr 魔力的时刻,我们只需要指定让程序运行到 `0x400844`,即验证通过时的位置,而不用管验证的逻辑是怎么样的。完整的 exp 如下,其他文件在 [github](../src/others/5.3.1_angr) 相应文件夹中。
|
||||
```python
|
||||
import angr
|
||||
#### 体系结构信息收集
|
||||
|
||||
project = angr.Project("entry_language", auto_load_libs=False)
|
||||
|
||||
@project.hook(0x400844)
|
||||
def print_flag(state):
|
||||
print "FLAG SHOULD BE:", state.posix.dump_fd(0)
|
||||
project.terminate_execution()
|
||||
|
||||
project.execute()
|
||||
```
|
||||
|
||||
Bingo!!!
|
||||
```
|
||||
$ python2 exp_angr.py
|
||||
FLAG SHOULD BE: Code_Talkers
|
||||
$ ./entry_language
|
||||
Enter the password: Code_Talkers
|
||||
Nice!
|
||||
```
|
||||
## CTF 实例
|
||||
查看章节 6.2.8。
|
||||
|
||||
|
||||
## 参考资料
|
||||
|
@ -307,9 +307,9 @@ projects 位于 `0x00202040`,proj_num 位于 `0x002020c0`。
|
||||
| | ; JMP XREF from 0x00000c67 (sub.read_bf0)
|
||||
\ `---> 0x00000c8e call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
|
||||
```
|
||||
正如我们一开始猜测的,这个函数是有问题的,如果输入 0 作为 length,则 length-1(能读入的实际长度) 后得到一个负数,在循环判断时,负数永远不会等于一个正数,于是将读入任意长度的字符串(以'\n'结尾),造成缓冲区溢出。
|
||||
正如我们一开始猜测的,这个函数是有问题的,如果输入 0 作为 length,则 length-1(能读入的实际长度) 后得到一个负数,在循环判断时,负数永远不会等于一个正数,于是将读入任意长度的字符串(以`\n`结尾),造成缓冲区溢出。
|
||||
|
||||
字符串末尾会被加上 '\x00',且开启了 Canary,暂时还没想到如何利用,继续往下看。另外特别注意 malloc 后得到的 project 的地址存放在 `rsp + 0x6a` 的位置。
|
||||
字符串末尾会被加上 `\x00`,且开启了 Canary,暂时还没想到如何利用,继续往下看。另外特别注意 malloc 后得到的 project 的地址存放在 `rsp + 0x6a` 的位置。
|
||||
|
||||
#### View all projects
|
||||
```
|
||||
|
@ -315,7 +315,7 @@ struct gundam *factory[9];
|
||||
```
|
||||
另外 gundam->name 指向一块 0x100 大小的空间。gundam 的数量存放在 `0x0020208c`。
|
||||
|
||||
从读入 name 的操作中我们发现,程序并没有在末尾设置 '\x00',可能导致信息泄漏(以'\x0a'结尾)。
|
||||
从读入 name 的操作中我们发现,程序并没有在末尾设置 `\x00`,可能导致信息泄漏(以`\x0a`结尾)。
|
||||
|
||||
#### Visit gundams
|
||||
```
|
||||
@ -612,7 +612,7 @@ gdb-peda$ x/6gx 0x555555757b50-0x10
|
||||
0x555555757b50: 0x0a41414141414141 0x00007ffff7dd2c78
|
||||
0x555555757b60: 0x0000000000000000 0x0000000000000000
|
||||
```
|
||||
可以看到程序并没有在字符串后加 '\x00' 隔断,所以可以将 unsorted bin 的地址泄漏出来,然后通过计算得到 libc 基址。
|
||||
可以看到程序并没有在字符串后加 `\x00` 隔断,所以可以将 unsorted bin 的地址泄漏出来,然后通过计算得到 libc 基址。
|
||||
|
||||
```
|
||||
[*] libc base: 0x7ffff79f8000
|
||||
|
@ -181,7 +181,7 @@ Which Secret do you want to wipe?
|
||||
| `-> 0x00400a25 leave
|
||||
\ 0x00400a26 ret
|
||||
```
|
||||
果然该函数使用 `calloc()` 为三种 secret 分别了不同大小的 chunk,small secret 属于 small chunk,big secret 和 huge secret 属于 large chunk。在分配前,会检查对应的 secret 是否已经存在,即每种 chunk 只能有一个,chunk 的指针放在 `.bss` 段上。另外其实读入 secret 的逻辑还是有问题的,它没有处理换行符,也没有在字符串末尾加 "\x00"。
|
||||
果然该函数使用 `calloc()` 为三种 secret 分别了不同大小的 chunk,small secret 属于 small chunk,big secret 和 huge secret 属于 large chunk。在分配前,会检查对应的 secret 是否已经存在,即每种 chunk 只能有一个,chunk 的指针放在 `.bss` 段上。另外其实读入 secret 的逻辑还是有问题的,它没有处理换行符,也没有在字符串末尾加 `\x00`。
|
||||
|
||||
#### Wipe secret
|
||||
```
|
||||
|
@ -212,9 +212,9 @@ Synchronization success.
|
||||
| 0x08048707 leave
|
||||
\ 0x08048708 ret
|
||||
```
|
||||
乍看之下似乎没有问题,在读入字符串末尾也加上了截断 "\x00"。
|
||||
乍看之下似乎没有问题,在读入字符串末尾也加上了截断 `\x00`。
|
||||
|
||||
但是,注意观察读入字符串和 malloc 返回地址在栈上的位置关系。字符串其实地址 `local_5ch`,最多 0x40 个字节,返回地址位于 `local_5ch + 0x40`,所以如果我们正好读入 0x40 字节,则 "\x00" 会被放到 `local_5ch + 0x41` 的位置,然后正好被返回地址给覆盖掉了。由于函数 `strcpy()` 是以 "\x00" 来决定字符串结尾的,所以字符串连上返回地址会被一起复制到堆上。然后又被一起打印出来。于是我们就得到了堆地址。
|
||||
但是,注意观察读入字符串和 malloc 返回地址在栈上的位置关系。字符串其实地址 `local_5ch`,最多 0x40 个字节,返回地址位于 `local_5ch + 0x40`,所以如果我们正好读入 0x40 字节,则 `\x00` 会被放到 `local_5ch + 0x41` 的位置,然后正好被返回地址给覆盖掉了。由于函数 `strcpy()` 是以 `\x00` 来决定字符串结尾的,所以字符串连上返回地址会被一起复制到堆上。然后又被一起打印出来。于是我们就得到了堆地址。
|
||||
|
||||
继续看函数 `sub.memset_84e`:
|
||||
```
|
||||
@ -303,7 +303,7 @@ Synchronization success.
|
||||
```
|
||||
同样的,Host 的返回地址放在 `local_9ch + 0x88` 的位置,而字符串最多到 `local_9ch + 0x44 + 0x40`,中间还间隔了 0x4 字节,所以不存在漏洞。但是 Org 的返回地址放在 `local_9ch + 0x40`,正好位于字符串的后面,所以存在漏洞。同时 Host 的字符串又正好位于 Org 返回地址的后面,所以 strcpy 会将 Org 字符串,返回地址和 Host 字符串全都复制到 Org 的堆上,造成堆溢出。利用这个堆溢出我们可以修改 top chunk 的 size,即 house-of-force。
|
||||
|
||||
当然这种漏洞有一定的几率不会成功,比如返回地址的低位本来就是 "\x00" 的时候,就恰好截断了。
|
||||
当然这种漏洞有一定的几率不会成功,比如返回地址的低位本来就是 `\x00` 的时候,就恰好截断了。
|
||||
|
||||
#### New note
|
||||
```
|
||||
|
@ -689,7 +689,7 @@ payload_1 += p32(leave_ret_addr)
|
||||
io.send(payload_1)
|
||||
```
|
||||
|
||||
从这里开始,后面的 paylaod 都是通过 read 函数读入的,所以必须为 100 字节长。首先,调用 write@plt 函数打印出与 base_addr 偏移 80 字节处的字符串 "/bin/sh",以验证栈转移成功。注意由于 `.dynstr` 中的字符串都是以 "\x00" 结尾的,所以伪造字符串为 "bin/sh\x00"。
|
||||
从这里开始,后面的 paylaod 都是通过 read 函数读入的,所以必须为 100 字节长。首先,调用 write@plt 函数打印出与 base_addr 偏移 80 字节处的字符串 "/bin/sh",以验证栈转移成功。注意由于 `.dynstr` 中的字符串都是以 `\x00` 结尾的,所以伪造字符串为 `bin/sh\x00`。
|
||||
```python
|
||||
payload_2 = "AAAA" # new ebp
|
||||
payload_2 += p32(write_plt)
|
||||
|
190
doc/6.2.8_re_defcampctf2015_entry_language.md
Normal file
190
doc/6.2.8_re_defcampctf2015_entry_language.md
Normal file
@ -0,0 +1,190 @@
|
||||
# 6.2.8 re DefcampCTF2015 entry_language
|
||||
|
||||
- [题目解析](#题目解析)
|
||||
- [参考资料](#参考资料)
|
||||
|
||||
|
||||
[下载文件](../src/writeup/6.2.8_re_defcampctf2015_entry_language)
|
||||
|
||||
## 题目解析
|
||||
这是一题标准的密码验证题,输入一个字符串,程序验证对误。
|
||||
```
|
||||
$ file entry_language
|
||||
defcamp_r100: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=0f464824cc8ee321ef9a80a799c70b1b6aec8168, stripped
|
||||
```
|
||||
```
|
||||
$ ./entry_language
|
||||
Enter the password: ABCD
|
||||
Incorrect password!
|
||||
```
|
||||
|
||||
为了与 angr 的自动化做对比,我们先使用传统的方法,逆向算法求解,`main` 函数和验证函数 `fcn.004006fd` 如下:
|
||||
```
|
||||
[0x00400610]> pdf @ main
|
||||
/ (fcn) main 153
|
||||
| main ();
|
||||
| ; var int local_110h @ rbp-0x110
|
||||
| ; var int local_8h @ rbp-0x8
|
||||
| ; DATA XREF from 0x0040062d (entry0)
|
||||
| 0x004007e8 55 push rbp
|
||||
| 0x004007e9 4889e5 mov rbp, rsp
|
||||
| 0x004007ec 4881ec100100. sub rsp, 0x110
|
||||
| 0x004007f3 64488b042528. mov rax, qword fs:[0x28] ; [0x28:8]=-1 ; '(' ; 40
|
||||
| 0x004007fc 488945f8 mov qword [local_8h], rax
|
||||
| 0x00400800 31c0 xor eax, eax
|
||||
| 0x00400802 bf37094000 mov edi, str.Enter_the_password: ; 0x400937 ; "Enter the password: "
|
||||
| 0x00400807 b800000000 mov eax, 0
|
||||
| 0x0040080c e8affdffff call sym.imp.printf ; int printf(const char *format)
|
||||
| 0x00400811 488b15500820. mov rdx, qword [obj.stdin] ; [0x601068:8]=0
|
||||
| 0x00400818 488d85f0feff. lea rax, [local_110h]
|
||||
| 0x0040081f beff000000 mov esi, 0xff ; 255
|
||||
| 0x00400824 4889c7 mov rdi, rax
|
||||
| 0x00400827 e8b4fdffff call sym.imp.fgets ; char *fgets(char *s, int size, FILE *stream)
|
||||
| 0x0040082c 4885c0 test rax, rax
|
||||
| ,=< 0x0040082f 7435 je 0x400866
|
||||
| | 0x00400831 488d85f0feff. lea rax, [local_110h]
|
||||
| | 0x00400838 4889c7 mov rdi, rax
|
||||
| | 0x0040083b e8bdfeffff call fcn.004006fd ; 调用验证函数
|
||||
| | 0x00400840 85c0 test eax, eax
|
||||
| ,==< 0x00400842 7511 jne 0x400855
|
||||
| || 0x00400844 bf4c094000 mov edi, str.Nice_ ; 0x40094c ; "Nice!"
|
||||
| || 0x00400849 e852fdffff call sym.imp.puts ; int puts(const char *s)
|
||||
| || 0x0040084e b800000000 mov eax, 0
|
||||
| ,===< 0x00400853 eb16 jmp 0x40086b
|
||||
| ||| ; JMP XREF from 0x00400842 (main)
|
||||
| |`--> 0x00400855 bf52094000 mov edi, str.Incorrect_password_ ; 0x400952 ; "Incorrect password!"
|
||||
| | | 0x0040085a e841fdffff call sym.imp.puts ; int puts(const char *s)
|
||||
| | | 0x0040085f b801000000 mov eax, 1
|
||||
| |,==< 0x00400864 eb05 jmp 0x40086b
|
||||
| ||| ; JMP XREF from 0x0040082f (main)
|
||||
| ||`-> 0x00400866 b800000000 mov eax, 0
|
||||
| || ; JMP XREF from 0x00400864 (main)
|
||||
| || ; JMP XREF from 0x00400853 (main)
|
||||
| ``--> 0x0040086b 488b4df8 mov rcx, qword [local_8h]
|
||||
| 0x0040086f 6448330c2528. xor rcx, qword fs:[0x28]
|
||||
| ,=< 0x00400878 7405 je 0x40087f
|
||||
| | 0x0040087a e831fdffff call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
|
||||
| | ; JMP XREF from 0x00400878 (main)
|
||||
| `-> 0x0040087f c9 leave
|
||||
\ 0x00400880 c3 ret
|
||||
[0x00400610]> pdf @ fcn.004006fd
|
||||
/ (fcn) fcn.004006fd 171
|
||||
| fcn.004006fd (int arg_bh);
|
||||
| ; var int local_38h @ rbp-0x38
|
||||
| ; var int local_24h @ rbp-0x24
|
||||
| ; var int local_20h @ rbp-0x20
|
||||
| ; var int local_18h @ rbp-0x18
|
||||
| ; var int local_10h @ rbp-0x10
|
||||
| ; arg int arg_bh @ rbp+0xb
|
||||
| ; CALL XREF from 0x0040083b (main)
|
||||
| 0x004006fd 55 push rbp
|
||||
| 0x004006fe 4889e5 mov rbp, rsp
|
||||
| 0x00400701 48897dc8 mov qword [local_38h], rdi
|
||||
| 0x00400705 c745dc000000. mov dword [local_24h], 0
|
||||
| 0x0040070c 48c745e01409. mov qword [local_20h], str.Dufhbmf ; 0x400914 ; "Dufhbmf"
|
||||
| 0x00400714 48c745e81c09. mov qword [local_18h], str.pG_imos ; 0x40091c ; "pG`imos"
|
||||
| 0x0040071c 48c745f02409. mov qword [local_10h], str.ewUglpt ; 0x400924 ; "ewUglpt"
|
||||
| 0x00400724 c745dc000000. mov dword [local_24h], 0
|
||||
| ,=< 0x0040072b eb6e jmp 0x40079b
|
||||
| | ; JMP XREF from 0x0040079f (fcn.004006fd)
|
||||
| .--> 0x0040072d 8b4ddc mov ecx, dword [local_24h]
|
||||
| :| 0x00400730 ba56555555 mov edx, 0x55555556
|
||||
| :| 0x00400735 89c8 mov eax, ecx
|
||||
| :| 0x00400737 f7ea imul edx
|
||||
| :| 0x00400739 89c8 mov eax, ecx
|
||||
| :| 0x0040073b c1f81f sar eax, 0x1f
|
||||
| :| 0x0040073e 29c2 sub edx, eax
|
||||
| :| 0x00400740 89d0 mov eax, edx
|
||||
| :| 0x00400742 01c0 add eax, eax
|
||||
| :| 0x00400744 01d0 add eax, edx
|
||||
| :| 0x00400746 29c1 sub ecx, eax
|
||||
| :| 0x00400748 89ca mov edx, ecx
|
||||
| :| 0x0040074a 4863c2 movsxd rax, edx
|
||||
| :| 0x0040074d 488b74c5e0 mov rsi, qword [rbp + rax*8 - 0x20]
|
||||
| :| 0x00400752 8b4ddc mov ecx, dword [local_24h]
|
||||
| :| 0x00400755 ba56555555 mov edx, 0x55555556
|
||||
| :| 0x0040075a 89c8 mov eax, ecx
|
||||
| :| 0x0040075c f7ea imul edx
|
||||
| :| 0x0040075e 89c8 mov eax, ecx
|
||||
| :| 0x00400760 c1f81f sar eax, 0x1f
|
||||
| :| 0x00400763 29c2 sub edx, eax
|
||||
| :| 0x00400765 89d0 mov eax, edx
|
||||
| :| 0x00400767 01c0 add eax, eax
|
||||
| :| 0x00400769 4898 cdqe
|
||||
| :| 0x0040076b 4801f0 add rax, rsi ; '+'
|
||||
| :| 0x0040076e 0fb600 movzx eax, byte [rax]
|
||||
| :| 0x00400771 0fbed0 movsx edx, al
|
||||
| :| 0x00400774 8b45dc mov eax, dword [local_24h]
|
||||
| :| 0x00400777 4863c8 movsxd rcx, eax
|
||||
| :| 0x0040077a 488b45c8 mov rax, qword [local_38h]
|
||||
| :| 0x0040077e 4801c8 add rax, rcx ; '&'
|
||||
| :| 0x00400781 0fb600 movzx eax, byte [rax]
|
||||
| :| 0x00400784 0fbec0 movsx eax, al
|
||||
| :| 0x00400787 29c2 sub edx, eax
|
||||
| :| 0x00400789 89d0 mov eax, edx
|
||||
| :| 0x0040078b 83f801 cmp eax, 1 ; 1
|
||||
| ,===< 0x0040078e 7407 je 0x400797 ; = 1 时跳转,验证成功
|
||||
| |:| 0x00400790 b801000000 mov eax, 1 ; 返回 1,验证失败
|
||||
| ,====< 0x00400795 eb0f jmp 0x4007a6
|
||||
| ||:| ; JMP XREF from 0x0040078e (fcn.004006fd)
|
||||
| |`---> 0x00400797 8345dc01 add dword [local_24h], 1 ; i = i + 1
|
||||
| | :| ; JMP XREF from 0x0040072b (fcn.004006fd)
|
||||
| | :`-> 0x0040079b 837ddc0b cmp dword [local_24h], 0xb ; [0xb:4]=-1 ; 11
|
||||
| | `==< 0x0040079f 7e8c jle 0x40072d ; i <= 11 时跳转
|
||||
| | 0x004007a1 b800000000 mov eax, 0 ; 返回 0
|
||||
| | ; JMP XREF from 0x00400795 (fcn.004006fd)
|
||||
| `----> 0x004007a6 5d pop rbp
|
||||
\ 0x004007a7 c3 ret
|
||||
```
|
||||
|
||||
整理后可以得到下面的伪代码:
|
||||
```C
|
||||
int fcn_004006fd(int *passwd) {
|
||||
char *str_1 = "Dufhbmf";
|
||||
char *str_2 = "pG`imos";
|
||||
char *str_3 = "ewUglpt";
|
||||
for (int i = 0; i <= 11; i++) {
|
||||
if((&str_3)[i % 3][2 * (1 / 3)] - *(i + passwd) != 1) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
然后写出逆向脚本:
|
||||
```python
|
||||
str_list = ["Dufhbmf", "pG`imos", "ewUglpt"]
|
||||
passwd = []
|
||||
for i in range(12):
|
||||
passwd.append(chr(ord(str_list[i % 3][2 * (i / 3)]) - 1))
|
||||
print ''.join(passwd)
|
||||
```
|
||||
|
||||
逆向算法似乎也很简单,但如果连算法都不用逆的话,下面就是见证 angr 魔力的时刻,我们只需要指定让程序运行到 `0x400844`,即验证通过时的位置,而不用管验证的逻辑是怎么样的。
|
||||
|
||||
完整的脚本如下:
|
||||
```python
|
||||
import angr
|
||||
|
||||
project = angr.Project("entry_language", auto_load_libs=False)
|
||||
|
||||
@project.hook(0x400844)
|
||||
def print_flag(state):
|
||||
print "FLAG SHOULD BE:", state.posix.dump_fd(0)
|
||||
project.terminate_execution()
|
||||
|
||||
project.execute()
|
||||
```
|
||||
|
||||
Bingo!!!
|
||||
```
|
||||
$ python2 exp_angr.py
|
||||
FLAG SHOULD BE: Code_Talkers
|
||||
$ ./entry_language
|
||||
Enter the password: Code_Talkers
|
||||
Nice!
|
||||
```
|
||||
|
||||
|
||||
## 参考资料
|
||||
- https://ctftime.org/task/1691
|
@ -135,37 +135,7 @@ flag hctf{?\_rev3rse\_iz\_s0\_?}
|
||||
print binascii.a2b_hex(str(hex(strings))[2:-1])
|
||||
```
|
||||
|
||||
结果:
|
||||
```
|
||||
qK┒
|
||||
h4r
|
||||
_;
|
||||
Vn
|
||||
L钔V
|
||||
sr姘
|
||||
j[瘶
|
||||
aDx€
|
||||
X-Ah
|
||||
O
|
||||
P
|
||||
u?
|
||||
l傡
|
||||
ck祕
|
||||
ZT~b
|
||||
Q=GJ
|
||||
w羆
|
||||
n?
|
||||
e掤t
|
||||
\{籠
|
||||
Sd凞
|
||||
JMM,
|
||||
p裦
|
||||
g?n
|
||||
^ⅧV
|
||||
U嬃>
|
||||
```
|
||||
|
||||
可以看到大多数字符都没有意义,除了 h4r 让人遐想联翩,可惜还是不全,但是结合已经分析出的 flag,猜测应该是 h4rd。
|
||||
从结果中可以看到大多数字符都没有意义,除了 h4r 让人遐想联翩,可惜还是不全,但是结合已经分析出的 flag,猜测应该是 h4rd。
|
||||
|
||||
flag hctf{??\_rev3rse\_iz\_s0\_h4rd?}
|
||||
```
|
||||
|
@ -38,6 +38,7 @@
|
||||
* [6.2.5 re PicoCTF2014 Baleful](6.2.5_re_picoctf2014_baleful.md)
|
||||
* [6.2.6 re SECCONCTF2017 printf_machine](6.2.6_re_secconctf2017_printf_machine.md)
|
||||
* [6.2.7 re CodegateCTF2018 RedVelvet](6.2.7_re_codegatectf2018_redvelvet.md)
|
||||
* [6.2.8 re DefcampCTF2015 entry_language](6.2.8_re_defcampctf2015_entry_language.md)
|
||||
* Web
|
||||
* [6.3.1 web HCTF2017 babycrack](6.3.1_web_hctf2017_babycrack.md)
|
||||
* Crypto
|
||||
|
1
doc/8.25_offsensive_techniques.md
Normal file
1
doc/8.25_offsensive_techniques.md
Normal file
@ -0,0 +1 @@
|
||||
# 8.25 (State of) The Art of War: Offensive Techniques in Binary Analysis
|
@ -27,3 +27,4 @@
|
||||
* [8.22 Practical Memory Checking With Dr. Memory](8.22_memory_checking.md)
|
||||
* [8.23 Evaluating the Effectiveness of Current Anti-ROP Defenses](8.23_current_anti-rop.md)
|
||||
* [8.24 How to Make ASLR Win the Clone Wars: Runtime Re-Randomization](8.24_runtime_re-randomization.md)
|
||||
* [8.25 (State of) The Art of War: Offensive Techniques in Binary Analysis](8.25_offsensive_techniques.md)
|
||||
|
Loading…
Reference in New Issue
Block a user