hacktricks/reversing-and-exploiting/reversing-tools-basic-methods
2024-04-06 18:13:07 +00:00
..
angr GitBook: No commit message 2024-04-06 18:13:07 +00:00
blobrunner.md GitBook: No commit message 2024-04-06 18:13:07 +00:00
cheat-engine.md GitBook: No commit message 2024-04-06 18:13:07 +00:00
README.md GitBook: No commit message 2024-04-06 18:13:07 +00:00
satisfiability-modulo-theories-smt-z3.md GitBook: No commit message 2024-04-06 18:13:07 +00:00

Reversing Tools & Basic Methods

从零开始学习AWS黑客技术成为专家 htARTEHackTricks AWS Red Team Expert

支持HackTricks的其他方式

Try Hard Security Group

{% embed url="https://discord.gg/tryhardsecurity" %}


基于ImGui的逆向工具

软件:

Wasm反编译器 / Wat编译器

在线工具:

软件:

.NET反编译器

dotPeek

dotPeek是一个反编译器可以反编译和检查多种格式,包括.dllWindows元数据文件.winmd可执行文件.exe。反编译后一个程序集可以保存为Visual Studio项目.csproj

这里的优点是如果需要从旧程序集中恢复丢失的源代码此操作可以节省时间。此外dotPeek提供了方便的导航功能使其成为Xamarin算法分析的完美工具之一。

.NET Reflector

具有全面的插件模型和API可以根据您的实际需求扩展工具以节省时间并简化开发。让我们看看这个工具提供的众多逆向工程服务

  • 提供数据如何在库或组件中流动的见解
  • 提供.NET语言和框架的实现和使用见解
  • 查找未记录和未公开的功能以更充分利用所使用的API和技术。
  • 查找依赖项和不同的程序集
  • 追踪代码中所有.NET代码的源代码的确切位置。

ILSpy & dnSpy

Visual Studio Code的ILSpy插件您可以在任何操作系统中使用它可以直接从VSCode安装无需下载git。点击Extensions,然后搜索ILSpy)。
如果您需要反编译修改重新编译,可以使用dnSpy或其积极维护的分支dnSpyEx。(右键单击 -> 修改方法**来更改函数内部的内容)。

DNSpy日志记录

为了让DNSpy在文件中记录一些信息,您可以使用以下代码片段:

using System.IO;
path = "C:\\inetpub\\temp\\MyTest2.txt";
File.AppendAllText(path, "Password: " + password + "\n");

DNSpy调试

要使用DNSpy调试代码您需要

首先,更改与调试相关的程序集属性

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]

至:

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default |
DebuggableAttribute.DebuggingModes.DisableOptimizations |
DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints |
DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]

然后点击编译

然后通过 文件 >> 保存模块... 保存新文件:

这是必要的,因为如果您不这样做,在运行时代码将应用几个优化,可能会导致在调试时断点永远不会触发或一些变量不存在

然后,如果您的.NET应用程序正在由IIS运行,您可以使用以下方法重新启动它:

iisreset /noforce

然后,为了开始调试,您应该关闭所有已打开的文件,并在调试选项卡中选择附加到进程...

然后选择w3wp.exe以附加到IIS服务器,然后点击附加

现在我们正在调试该进程是时候停止它并加载所有模块了。首先点击_Debug >> Break All_然后点击_Debug >> Windows >> Modules_

点击Modules中的任何模块,然后选择打开所有模块

右键单击Assembly Explorer中的任何模块,然后点击排序程序集

Java反编译器

https://github.com/skylot/jadx
https://github.com/java-decompiler/jd-gui/releases

调试DLLs

使用IDA

  • 加载rundll3264位位于C:\Windows\System32\rundll32.exe32位位于C:\Windows\SysWOW64\rundll32.exe
  • 选择Windbg调试器
  • 选择“在库加载/卸载时暂停

  • 配置执行的参数,放入DLL的路径和要调用的函数:

然后,当您开始调试时,每次加载DLL时执行将会停止然后当rundll32加载您的DLL时执行将会停止。

但是如何访问已加载的DLL的代码呢使用这种方法我不知道如何做。

使用x64dbg/x32dbg

  • 加载rundll3264位位于C:\Windows\System32\rundll32.exe32位位于C:\Windows\SysWOW64\rundll32.exe
  • 更改命令行文件 --> 更改命令行并设置dll的路径和要调用的函数例如“C:\Windows\SysWOW64\rundll32.exe” “Z:\shared\Cybercamp\rev2\\14.ridii_2.dll”,DLLMain
  • 更改_Options --> Settings_并选择“DLL入口”。
  • 然后开始执行调试器将在每个dll主函数处停止最终您将停在您的dll的dll入口处。从那里,只需搜索您想要设置断点的位置。

请注意当执行由于任何原因停止在win64dbg中时您可以看到您正在查看的代码位于win64dbg窗口顶部

然后查看此处时您可以看到执行已在您要调试的dll中停止。

GUI应用程序/视频游戏

Cheat Engine是一个有用的程序,可用于查找运行游戏内存中保存的重要值并更改它们。更多信息请参见:

{% content-ref url="cheat-engine.md" %} cheat-engine.md {% endcontent-ref %}

ARM和MIPS

{% embed url="https://github.com/nongiach/arm_now" %}

Shellcode

使用blobrunner调试shellcode

Blobrunner将在内存空间中分配shellcode并将向您指示shellcode分配的内存地址,然后将停止执行。
然后您需要将调试器Ida或x64dbg附加到进程,并在指示的内存地址处设置断点,然后恢复执行。这样您就可以调试shellcode了。

发布的github页面包含了编译版本的zip文件https://github.com/OALabs/BlobRunner/releases/tag/v0.0.5
您可以在以下链接中找到Blobrunner的略微修改版本。为了编译它只需在Visual Studio Code中创建一个C/C++项目,复制并粘贴代码,然后构建

{% content-ref url="blobrunner.md" %} blobrunner.md {% endcontent-ref %}

使用jmp2it调试shellcode

jmp2it 与blobrunner非常相似。它将在内存空间中分配shellcode,并启动一个永久循环。然后,您需要将调试器附加到进程,开始等待2-5秒然后停止,您将发现自己处于永久循环中。跳转到永久循环的下一条指令因为它将是对shellcode的调用最终您将发现自己正在执行shellcode。

您可以在发布页面中下载jmp2it的编译版本

使用Cutter调试shellcode

Cutter是radare的GUI。使用Cutter您可以动态模拟和检查shellcode。

请注意Cutter允许您“打开文件”和“打开shellcode”。在我的情况下当我将shellcode作为文件打开时它正确反编译了但当我将其作为shellcode打开时则没有

为了从想要的位置开始模拟设置一个断点显然Cutter将自动从那里开始模拟

您可以在十六进制转储中查看堆栈,例如:

解混淆shellcode并获取执行函数

您应该尝试scdbg
它将告诉您shellcode正在使用的哪些函数以及shellcode是否在内存中解码自身。

scdbg.exe -f shellcode # Get info
scdbg.exe -f shellcode -r #show analysis report at end of run
scdbg.exe -f shellcode -i -r #enable interactive hooks (file and network) and show analysis report at end of run
scdbg.exe -f shellcode -d #Dump decoded shellcode
scdbg.exe -f shellcode /findsc #Find offset where starts
scdbg.exe -f shellcode /foff 0x0000004D #Start the executing in that offset

scDbg还配备了一个图形启动器您可以在其中选择所需的选项并执行shellcode

创建Dump选项将在内存中动态更改shellcode时转储最终shellcode可用于下载解码后的shellcode起始偏移量对于在特定偏移处启动shellcode很有用。调试Shell选项可用于使用scDbg终端调试shellcode但我发现前面解释的任何选项在这方面都更好因为您可以使用Ida或x64dbg

使用CyberChef进行反汇编

将您的shellcode文件上传为输入并使用以下配方对其进行反编译https://gchq.github.io/CyberChef/#recipe=To_Hex('Space',0)Disassemble_x86('32','Full%20x86%20architecture',16,0,true,true)

Movfuscator

这个混淆器修改所有mov指令(是的,非常酷)。它还使用中断来改变执行流。有关其工作原理的更多信息:

如果您很幸运,demovfuscator将对二进制文件进行反混淆。它有几个依赖项

apt-get install libcapstone-dev
apt-get install libz3-dev

安装keystone (apt-get install cmake; mkdir build; cd build; ../make-share.sh; make install)

如果你在玩一个CTF这个绕过方法来找到flag可能会非常有用https://dustri.org/b/defeating-the-recons-movfuscator-crackme.html

Rust

要找到入口点,搜索函数中的::main,如下所示:

在这种情况下二进制文件被称为authenticator所以很明显这是一个有趣的主函数。
有了被调用的函数的名称,在互联网上搜索它们,了解它们的输入输出

Delphi

对于Delphi编译的二进制文件可以使用https://github.com/crypto2011/IDR

如果你需要反向一个Delphi二进制文件我建议你使用IDA插件https://github.com/Coldzer0/IDA-For-Delphi

只需按下ATL+f7在IDA中导入Python插件然后选择Python插件。

这个插件将在调试开始时执行二进制文件并动态解析函数名称。在开始调试后再次按下开始按钮绿色按钮或f9将在真正代码的开头触发断点。

这也非常有趣,因为如果你在图形应用程序中按下一个按钮,调试器将停在被该按钮执行的函数中。

Golang

如果你需要反向一个Golang二进制文件我建议你使用IDA插件https://github.com/sibears/IDAGolangHelper

只需按下ATL+f7在IDA中导入Python插件然后选择Python插件。

这将解析函数的名称。

编译的Python

在这个页面上你可以找到如何从一个ELF/EXE Python编译的二进制文件中获取Python代码

{% content-ref url="../../generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md" %} .pyc.md {% endcontent-ref %}

GBA - Game Body Advance

如果你得到一个GBA游戏的二进制文件,你可以使用不同的工具来模拟调试它:

no$gba在_Options --> Emulation Setup --> Controls_** **你可以看到如何按下Game Boy Advance的按钮

按下时,每个键都有一个值来识别它:

A = 1
B = 2
SELECT = 4
START = 8
RIGHT = 16
LEFT = 32
UP = 64
DOWN = 128
R = 256
L = 256

因此在这种程序中有趣的部分将是程序如何处理用户输入。在地址0x4000130处您将找到常见的函数KEYINPUT。

在上图中您可以发现该函数是从FUN_080015a8地址0x080015fa和0x080017ac调用的。

在该函数中,在进行一些初始化操作之后(没有任何重要性):

void FUN_080015a8(void)

{
ushort uVar1;
undefined4 uVar2;
undefined4 uVar3;
ushort uVar4;
int iVar5;
ushort *puVar6;
undefined *local_2c;

DISPCNT = 0x1140;
FUN_08000a74();
FUN_08000ce4(1);
DISPCNT = 0x404;
FUN_08000dd0(&DAT_02009584,0x6000000,&DAT_030000dc);
FUN_08000354(&DAT_030000dc,0x3c);
uVar4 = DAT_030004d8;

发现了这段代码:

do {
DAT_030004da = uVar4; //This is the last key pressed
DAT_030004d8 = KEYINPUT | 0xfc00;
puVar6 = &DAT_0200b03c;
uVar4 = DAT_030004d8;
do {
uVar2 = DAT_030004dc;
uVar1 = *puVar6;
if ((uVar1 & DAT_030004da & ~uVar4) != 0) {

最后的if语句检查**uVar4是否在最后的Keys中,而不是当前的密钥,也称为释放按钮(当前密钥存储在uVar1**中)。

if (uVar1 == 4) {
DAT_030000d4 = 0;
uVar3 = FUN_08001c24(DAT_030004dc);
FUN_08001868(uVar2,0,uVar3);
DAT_05000000 = 0x1483;
FUN_08001844(&DAT_0200ba18);
FUN_08001844(&DAT_0200ba20,&DAT_0200ba40);
DAT_030000d8 = 0;
uVar4 = DAT_030004d8;
}
else {
if (uVar1 == 8) {
if (DAT_030000d8 == 0xf3) {
DISPCNT = 0x404;
FUN_08000dd0(&DAT_02008aac,0x6000000,&DAT_030000dc);
FUN_08000354(&DAT_030000dc,0x3c);
uVar4 = DAT_030004d8;
}
}
else {
if (DAT_030000d4 < 8) {
DAT_030000d4 = DAT_030000d4 + 1;
FUN_08000864();
if (uVar1 == 0x10) {
DAT_030000d8 = DAT_030000d8 + 0x3a;

在前面的代码中,您可以看到我们正在将uVar1(按下按钮的值所在的位置)与一些值进行比较:

  • 首先,它与值4SELECT按钮)进行比较:在挑战中,此按钮清除屏幕
  • 然后,它与值8START按钮)进行比较:在挑战中,这会检查代码是否有效以获取标志。
  • 在这种情况下,将变量**DAT_030000d8**与0xf3进行比较如果值相同则执行一些代码。
  • 在任何其他情况下会检查一些contDAT_030000d4。这是一个cont因为在进入代码后立即加1。
  • 如果小于8则会执行涉及向**DAT_030000d8**添加值的操作基本上是将按下的键的值添加到此变量中只要cont小于8

因此,在这个挑战中,了解按钮的值,您需要按下长度小于8的组合使得结果相加为0xf3

本教程的参考资料: https://exp.codes/Nostalgia/

Game Boy

{% embed url="https://www.youtube.com/watch?v=VVbRe7wr3G4" %}

课程

Try Hard Security Group

{% embed url="https://discord.gg/tryhardsecurity" %}

从零开始学习AWS黑客技术成为专家 htARTEHackTricks AWS Red Team Expert

支持HackTricks的其他方式