浅析shellcode 反汇编模拟运行及调试方法
<p>onlinedisassembler</p><p>https://onlinedisassembler.com 在线反汇编工具,类似于lda。功能比较单一。</p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083452118.jpg" /></p>
<p>Any.run 等平台在线分析</p>
<ul>
<li>将shellcode保存为文件</li>
<li>通过如下脚本,转换shellcode为char数组</li>
</ul>
<div class="jb51code">
<pre class="brush:plain;">
import binascii
filename = "C:\\Users\\liang\\Desktop\\工作相关\\样本\\rdpscan\\rdpscan\\ssleay32.dll"
#filename = "C:\\Users\\liang\\Desktop\\payload"
shellcode = "{"
ctr = 1
maxlen = 15
for b in open(filename, "rb").read():
shellcode += "0x" + str(binascii.hexlify(b.to_bytes(length=1, byteorder='big'))) + ","
if ctr == maxlen:
shellcode += "\n"
ctr = 0
ctr += 1
shellcode = shellcode[:-1] + "}"
print(shellcode)</pre>
</div>
<p>1,将结果复制到char shellcode处,并 通过如下vs程序加载shellcod</p>
<div class="jb51code">
<pre class="brush:plain;">
#include <windows.h>
#include <stdio.h>
#include <string.h>
#pragma comment(linker, "/section:.data,RWE")
unsigned char shellcode[] = 复制到这里
typedef void(__stdcall* CODE) ();
int main()
{
PVOID p = NULL;
if ((p = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)) == NULL)
MessageBoxA(NULL, "申请内存失败", "提醒", MB_OK);
if (!(memcpy(p, shellcode, sizeof(shellcode))))
MessageBoxA(NULL, "写内存失败", "提醒", MB_OK);
CODE code = (CODE)p;
code();
return 0;
}
</pre>
</div>
<p>1.设置c运行库的静态编译,如图设置,将运行库设置为多线程/MT</p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083452119.jpg" /></p>
<p>点击生成解决方案,将生成的exe上传至Any.run去分析如图,即可通过在线分析平台去分析shellcode。简单快捷</p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083452120.jpg" /></p>
<p><strong>槽点主要有如下几方面:</strong></p>
<ul>
<li>一定要选择静态编译c运行库,因为Any.run 的运行库可能会不全。以防万一</li>
<li>shellcode不可以是\xFF 这类形式,必须是0xFF。因为前者属于字符串,后者属于数组。待分析的shellcode较大,超过65535字节后,vs在编译时会报错 fatal error C1091: compiler limit: string exceeds 65535 bytes in length</li>
<li></li>
</ul>
<p><strong>scdbg</strong></p>
<p>windows shellcode运行模拟器,模拟运行shellcode 对于简单的shellcode 推荐使用此方法,模拟运行找到c2地址</p>
<p>使用文章以及介绍</p>
<p>https://isc.sans.edu/forums/diary/Analyzing+Encoded+Shellcode+with+scdbg/24134</p>
<p>优点</p>
<ul>
<li>支持debug shellcode</li>
<li>dum内存</li>
<li>重定向tcp请求到其他机器,但是不支持urlopen等函数</li>
</ul>
<p>缺点:</p>
<p>功能较为单一,模拟运行不是很全。有时候可能执行不到某些流程。并且没有实现部分dll的导出函数图片</p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083453121.jpg" /></p>
<p>下载链接</p>
<p>http://sandsprite.com/CodeStuff/scdbg.zip</p>
<p>miasm</p>
<p>miasm是一个python llvm写的逆向工程框架。</p>
<p>但是官方中提供了很多例子,我们可以直接利用官方提供的脚本去完成很多任务</p>
<p>miasm不仅仅支持pe文件,还支持elf等,支持x86,arm,mips等架构</p>
<p>miasm功能不仅仅局限于这些,还有很多好玩的功能,例如自动化脱壳等。参考</p>
<p>https://miasm.re/blog/index.htmlhttps://github.com/cea-sec/miasm/</p>
<p><strong>miasm 反编译shellcode</strong></p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083453122.jpg" /></p>
<p>使用graphviz 加载got文件,获得如下</p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083453123.jpg" /></p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083454124.jpg" /></p>
<p>同理 arm的选择arm,mips选择mips处理器类型</p>
<p>如果不像使用官方自带,可以自己写</p>
<p>沙箱中运行shellcode</p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083454125.jpg" /></p>
<p>记录每步运行的各种寄存器的值</p>
<p>沙箱中运行可执行系统文件</p>
<p>在知道系统架构的情况下 可以选择相应系统架构的sandbox,运行shellcode,从而获得更多信息</p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083454126.jpg" /></p>
<p>可以支持自写dll,方便hook,如图,但是我没写</p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083454127.jpg" /></p>
<p>支持的系统架构如下</p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083455128.jpg" /></p>
<p>其他功能</p>
<p>1.添加断点</p>
<div class="jb51code">
<pre class="brush:plain;">
# A breakpoint callback takes the jitter as first parameterdef dump(jitter):
# Dump data ad address run_addr with a length of len(data)
new_data = jitter.vm.get_mem(run_addr, len(data))
# Save to disk
open('/tmp/dump.bin', 'wb').write(new_data)
# Stop execution
return False
# Register a callback to the breakpointmyjit.add_breakpoint(0x4000004b, dump)...myjit.cpu.EAX = 0x40000000myjit.init_run(run_addr)myjit.continue_run()</pre>
</div>
<p>1.hook沙箱中系统函数和peb等和数据结构例如hook urlmon_URLDownloadToCacheFileW</p>
<div class="jb51code">
<pre class="brush:plain;">
def urlmon_URLDownloadToCacheFileW(jitter):
ret_ad, args = jitter.func_args_stdcall(["lpunkcaller",
"szurl",
"szfilename",
"ccfilename",
"reserved",
"pbsc"])
url = jitter.get_str_unic(args.szurl)
print "URL:", url
jitter.set_str_unic(args.szfilename, "toto")
jitter.func_ret_stdcall(ret_ad, 0)</pre>
</div>
<p>注意 有时候程序调用沙箱没有实现的api,则需要通过上述该方法自己实现一个 sandbox 默认只实现了以下几个dll的导出函数 ntdll.dll", "kernel32.dll", "user32.dll", "ole32.dll", "urlmon.dll", "ws2_32.dll", 'advapi32.dll', "psapi.dll"</p>
<p>1.读写并修改系统可执行文件</p>
<p>例如pe文件的修改,添加.text区段,修改pe文件结构等。当然,也支持elf,mach-o文件的修改等</p>
<div class="jb51code">
<pre class="brush:plain;">
import sys
from elfesteem import pe_init
# Get the shellcode
data = open(sys.argv).read()
# Generate a PE
pe = pe_init.PE(wsize=32)
# Add a ".text" section containing the shellcode to the PE
s_text = pe.SHList.add_section(name=".text", addr=0x1000, data=data)
# Set the entrypoint to the shellcode's address
pe.Opthdr.AddressOfEntryPoint = s_text.addr
# Write the PE to "sc_pe.py"
open('sc_pe.exe', 'w').write(str(pe))</pre>
</div>
<p></p>
<p>思维扩展sandbox加载一个pe文件在pe文件中申请一段内存,存放shellcode修改eip到shellcode处运行</p>
<p>好处,可以结合pe文件自动分析,分析处该shellcode的具体行为</p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083455129.jpg" /></p>
<p>OD加载shellcode</p>
<p>方法一</p>
<p>需要安装Olly Advanced 插件</p>
<p>随便load一个应用程序Alt+m 打开内存页面,添加内存,如图</p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083455130.jpg" /></p>
<p style="text-align: left">将shellcode复制进去设置新的eip</p>
<p>方法二</p>
<p>该方法灵活应用</p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083455131.jpg" /></p>
<p>如图我们可以看出,加载shellcode的方式有以下几个步骤</p>
<p>调用virtualloc申请内存,属性为可写可执行。用来存放shellcode</p>
<p>调用createprocess 执行shellcode</p>
<p>注意,并不是一定通过createprocess去执行shellcode。也可以通过内联汇编jmp,setThreadContext等方式去执行shellcode。理论上,只要可以修改eip,就可以执行shellcode</p>
<p>od中输入命令 <code>bp createprocess</code></p>
<p>等运行shellcode的时候,od会自动停在createprocess处,也就是shellcode开始执行的位置。如图</p>
<p style="text-align: center"><img alt="" src="https://img.jbzj.com/file_images/article/202002/20200218083456132.jpg" /></p>
<p><span style="color: #ff0000"><strong>总结</strong></span></p>
<p>以上所述是小编给大家介绍的浅析shellcode 反汇编模拟运行及调试方法,希望对大家有所帮助!</p>
<div class="art_xg">
<b>您可能感兴趣的文章:</b><ul><li>iOS安全防护系列之ptrace反调试与汇编调用系统方法详解</li><li>在 Visual Studio 中查看反汇编代码</li></ul>
</div>
</div>
<!--endmain-->
頁:
[1]