0
点赞
收藏
分享

微信扫一扫

分析Windows二进制文件和嵌入式资源


环境介绍

可以去看一下我上一篇文章

开始

将题目解压到目录里

分析Windows二进制文件和嵌入式资源_安全


一共有48个可执行程序

分析Windows二进制文件和嵌入式资源_经验分享_02


我们随意选择一个文件拖入ida分析一下

用peid分析一下文件,发现这个程序是32位的,而且没有加密和混淆

分析Windows二进制文件和嵌入式资源_经验分享_03


将文件拖入ida

分析Windows二进制文件和嵌入式资源_经验分享_04


如果以后遇到不知道程序从哪开始的话,可以查看左边那一栏的函数,或者windows特别查找导入

分析Windows二进制文件和嵌入式资源_字符串_05


分析Windows二进制文件和嵌入式资源_安全_06


可以看到,这个二进制文件导入了这些函数,我们可以获得很多信息

分析Windows二进制文件和嵌入式资源_网络安全_07

isdebuggerpresnt这个函数是遇到错误时执行的,说明我们在此程序里需要规避一些东西

分析Windows二进制文件和嵌入式资源_字符串_08


这个程序还有打开,读取和写入文件的功能,获得这些信息对之后的逆向很有用,这些的外部参照,交叉引用很可能在实现一些很重要的东西

ctrl+f12,查找一下程序中存在的字符串

分析Windows二进制文件和嵌入式资源_字符串_09


看起来并没有什么有用的信息,在这种情况下,我们必须手动指定字符串的类型,打开ida的选项,选择字符串

分析Windows二进制文件和嵌入式资源_网络安全_10


分析Windows二进制文件和嵌入式资源_字符串_11


在linux二进制文件中看到一个字符串通常只是字节,然后以空值结尾

"ABCD\x00"

但是在windows上,它通常是16位,因此字符串始终基于字符,空字符,字符,空字符,字符,空字符这样的

"A\x00B\x00C\x00D\x00......."

如果在ida里ctrl+f12里是默认寻找linux的c字符串,所以在做windowsPE文件时,通常找不到它们

但是在ida里我们可以手动选择查找字符串的方式,这种情况下,c 16bits可以查看字符串

分析Windows二进制文件和嵌入式资源_加载_12


分析Windows二进制文件和嵌入式资源_加载_13


现在找到了有意义的字符串,在这里,我们可以看到这个程序要求我们输入密码,双击这个字符串,去到调用的地方

分析Windows二进制文件和嵌入式资源_网络安全_14

分析Windows二进制文件和嵌入式资源_加载_15


分析Windows二进制文件和嵌入式资源_经验分享_16


看下空格,进入可视化界面

分析Windows二进制文件和嵌入式资源_字符串_17


可以看到,这个地方就是它加载的地址

分析Windows二进制文件和嵌入式资源_经验分享_18


然后调用了这个sub,这可能是printf,然后是格式化字符串%s

分析Windows二进制文件和嵌入式资源_经验分享_19


我们跟踪一下这个sub,我们就会看到scanf

分析Windows二进制文件和嵌入式资源_经验分享_20


所以这只是围绕scanf实现的一些函数包装,我们重命名一下这些调用函数的名字,之后看起来会一目了然

分析Windows二进制文件和嵌入式资源_安全_21


分析Windows二进制文件和嵌入式资源_安全_22


这个程序在这里读取了我们输入的字符后,然后做了一个if判断

分析Windows二进制文件和嵌入式资源_加载_23


所以最后一个调用的函数是用来检查我们输入的字符串的

分析Windows二进制文件和嵌入式资源_网络安全_24


我们将它重命名为check_password

分析Windows二进制文件和嵌入式资源_安全_25


我们双击进入这个函数

分析Windows二进制文件和嵌入式资源_加载_26


发现在这个函数的开头,加载了一个字符串"IronManSucks",在下面还有一些循环,并且比较了一些东西,所以这很有可能是密码

我们执行这个程序,然后输入IronManSucks

分析Windows二进制文件和嵌入式资源_经验分享_27


但是并没有什么其他的东西显示出来,但我们还需要考虑一件事,那就是为什么有40多个程序,它们是如何归属在一起的,它们是相同的还是不同的?我随意复制了两个程序到linux上做对比

分析Windows二进制文件和嵌入式资源_加载_28


我们使用hexdump进行比较

cat 程序 | hexdump -C > a.out
cat 程序2 | hexdump -C > b.out

分析Windows二进制文件和嵌入式资源_加载_29


然后使用vimdiff比较它们

vimdiff a.out b.out

分析Windows二进制文件和嵌入式资源_加载_30


我们可以看到,这两个文件非常不一样,我们去ida里看一下源代码

分析Windows二进制文件和嵌入式资源_网络安全_31


emm…看得头疼,我打算用ghidra来看一下源代码

关于安装和使用ghidar的方法可以去看我之前的文章,进入ghidar后反汇编main函数

分析Windows二进制文件和嵌入式资源_经验分享_32


看起来舒服多了

分析Windows二进制文件和嵌入式资源_加载_33


分析Windows二进制文件和嵌入式资源_网络安全_34


这个程序最后的一句话是叫我们去踩…砖?这个地方是检查密码的地方

分析Windows二进制文件和嵌入式资源_字符串_35


我以为密码是IronManSucks,但是是不对的,所以我们重新分析一下检查密码的函数

分析Windows二进制文件和嵌入式资源_安全_36


看得头疼,我们回到ida,进入可视化界面

分析Windows二进制文件和嵌入式资源_字符串_37


可以看到,在经过比较后,它成功打印出了Oh,hello Batban字符串,但是另一个判断里有更多的代码,我将两个程序检查密码的函数反汇编对比了一下,发现都是差不多的

分析Windows二进制文件和嵌入式资源_字符串_38


字符串比较的值是当前未映射的地址

分析Windows二进制文件和嵌入式资源_安全_39


这是程序在执行时来自动态内存的值,所以还有一个密码,当我们查看此地址其他位置的交叉引用时,我们会跳转到此位置

分析Windows二进制文件和嵌入式资源_加载_40


memcpy,说明有一些字符串从某个地方复制到这个地址,并且复制的字符串在eax寄存器中,双击调用的函数

分析Windows二进制文件和嵌入式资源_网络安全_41

分析Windows二进制文件和嵌入式资源_经验分享_42


按下f5查看源代码

分析Windows二进制文件和嵌入式资源_经验分享_43


可以看到,它执行了FindResourceW后又执行了LoadResource,这个函数在可执行文件中查找资源并加载它,他加载了这些数据,然后复制到该区域

分析Windows二进制文件和嵌入式资源_网络安全_44


然后我们使用x32dbg来调试这个程序,直接运行到叫我们输入密码的位置

分析Windows二进制文件和嵌入式资源_网络安全_45


然后我在字符串周围的堆栈找到这个返回地址

分析Windows二进制文件和嵌入式资源_经验分享_46


分析Windows二进制文件和嵌入式资源_字符串_47


然后跳转到此地址进行分析

分析Windows二进制文件和嵌入式资源_加载_48


分析Windows二进制文件和嵌入式资源_网络安全_49


右击跟踪此函数

分析Windows二进制文件和嵌入式资源_安全_50


进入此函数后,在下面找到一些有趣的东西

分析Windows二进制文件和嵌入式资源_网络安全_51


这个密码是被引用的,所以看起来像另一个密码,我们在此处设置一个断点,然后输入密码

分析Windows二进制文件和嵌入式资源_网络安全_52


分析Windows二进制文件和嵌入式资源_经验分享_53


按F8一步一步慢慢调试

分析Windows二进制文件和嵌入式资源_网络安全_54


可以看到,这里一直在比较字符串的值,然后继续往下

分析Windows二进制文件和嵌入式资源_网络安全_55


然后输出了正确的答案,他输入了一个图片,然后说是m

在之前分析程序函数的时候,这个程序有读取和写入文件的功能

分析Windows二进制文件和嵌入式资源_网络安全_56


我们打开图片看一下

分析Windows二进制文件和嵌入式资源_经验分享_57


这个图片编号为35,现在我们只需要将字母对应的编号排列起来即可

但是文件太多了,我们不能全部都一对一调试,不然浪费的时间太多了,于是我又返回逆向分析

然后发现他加载的资源非常大,但是我们的密码很短

分析Windows二进制文件和嵌入式资源_安全_58


然后我在data段里到处找,最终找到了一个其他部分引用了该区域内的数据

分析Windows二进制文件和嵌入式资源_网络安全_59


分析Windows二进制文件和嵌入式资源_加载_60


然后发现了这个xor函数,这里有一个循环和一个常数值的异或操作,在下面还能看到被压入的堆栈常量和异或的地址,这里其实是两个不同东西的异或,它们都指向BRICK加载内容,然后根据它们的地址和BRICL的起始地址,我们可以计算它们的在BRICK数据中的偏移量

分析Windows二进制文件和嵌入式资源_网络安全_61


分析Windows二进制文件和嵌入式资源_加载_62


emm…总结一下:

现在我们知道了有一个隐藏的密码是从一个名为BRICK的嵌入式资源加载的
然后执行程序可以使用这个隐藏的密码获得图像
我们还有两个隐藏的xor加密的字符串

我们需要写一个python程序来读取在BRICK的资源,我们需要一个可以处理PE文件的模块
然后我在github上找到了这个

https://github.com/erocarrera/pefile

分析Windows二进制文件和嵌入式资源_网络安全_63


然后我在linux机子上安装了这个模块

分析Windows二进制文件和嵌入式资源_网络安全_64


然后试一下能否处理PE文件

分析Windows二进制文件和嵌入式资源_安全_65


从第一个条目里所有的目录中,通过遍历终于找到了一些数据,我们从二进制文件内部得到的偏移量+大小,而且大小还和在ida里看到的一样

分析Windows二进制文件和嵌入式资源_安全_66


分析Windows二进制文件和嵌入式资源_网络安全_67


使用CFF Explorer可以确认密码位于BRICK:id_101资源数据的开头

分析Windows二进制文件和嵌入式资源_安全_68


使用LIEF从 PE 资源部分提取密码

https://github.com/lief-project/LIEF

分析Windows二进制文件和嵌入式资源_网络安全_69


由于我python太差,我在这里贴上其他大佬的解题脚本

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import lief

def get_code(filename):
    binary = lief.parse(filename)
    brick = binary.resources.childs.next()
    id_101 = brick.childs.next()
    data = id_101.childs.next().content

    code = ""
    has_zero = False
    for d in data:
        if d == 0:
            if has_zero == True:
                break
            else:
                has_zero = True
        else:
            has_zero = False
            code += chr(d)
    print("{} => {}".format(filename, code))

for _, _, files in os.walk("."):
    for f in files:
        if f.endswith(".exe"):
            get_code(f)

运行脚本后根据得到的密码来获得图片

from subprocess import Popen, PIPE, STDOUT
import os

passcode = dict()
passcode["1BpnGjHOT7h5vvZsV4vISSb60Xj3pX5G.exe"] = "ZImIT7DyCMOeF6"
passcode["1JpPaUMynR9GflWbxfYvZviqiCB59RcI.exe"] = "PylRCpDK"
passcode["2AljFfLleprkThTHuVvg63I7OgjG2LQT.exe"] = "UvCG4jaaIc4315"
passcode["3Jh0ELkck1MuRvzr8PLIpBNUGlspmGnu.exe"] = "uVmH96JGdPkEBfd"
passcode["4ihY3RWK4WYqI4XOXLtAH6XV5lkoIdgv.exe"] = "3nEiXqMnXG"
passcode["7mCysSKfiHJ4WqH2T8ERLE33Wrbp6Mqe.exe"] = "Q9WdIAGjUKdNxr6"
passcode["AEVYfSTJwubrlJKgxV8RAl0AdZJ5vhhy.exe"] = "UkuAJxmt8"
passcode["aSfSVMn7B8eRtxgJgwPP5Y5HiDEidvKg.exe"] = "b1VRfMTNPu"
passcode["azcyERV8HUbXmqPTEq5JFt7Ax1W5K4wl.exe"] = "qNb6tr7n"
passcode["BG3IDbHOUt9yHumPceLTVbObBHFneYEu.exe"] = "KSL8EAnlIZin1gG"
passcode["Bl0Iv5lT6wkpVCuy7jtcva7qka8WtLYY.exe"] = "uLKEIRAEn"
passcode["bmYBZTBJlaFNbbwpiOiiQVdzimx8QVTI.exe"] = "7kcuVMWeIBFGWfJ"
passcode["Bp7836noYu71VAWc27sUdfaGwieALfc2.exe"] = "NcMkqwelbRu"
passcode["cWvFLbliUfJl7KFDUYF1ABBFYFb6FJMz.exe"] = "yu7hNshnpM4Vy"
passcode["d4NlRo5umkvWhZ2FmEG32rXBNeSSLt2Q.exe"] = "5xj9HmHyhF"
passcode["dnAciAGVdlovQFSJmNiPOdHjkM3Ji18o.exe"] = "ZYNGeumv6QuI7"
passcode["dT4Xze8paLOG7srCdGLsbLE1s6m3EsfX.exe"] = "dRnTVwZPjf0U"
passcode["E36RGTbCE4LDtyLi97l9lSFoR7xVMKGN.exe"] = "dPVLAQ8LwmhH"
passcode["eEJhUoNbuc40kLHRo8GB7bwFPkuhgaVN.exe"] = "J1kj42jZsC9"
passcode["eovBHrlDb809jf08yaAcSzcX4T37F1NI.exe"] = "rXZE7pDx3"
passcode["Ew93SSPDbgiQYo4E4035A16MJUxXegDW.exe"] = "eoneTNuryZ3eF"
passcode["gFZw7lPUlbOXBvHRc31HJI5PKwy745Wv.exe"] = "jZAorSlICuQa0g8"
passcode["hajfdokqjogmoWfpyp4w0feoeyhs1QLo.exe"] = "hqpNm7VJL"
passcode["HDHugJBqTJqKKVtqi3sfR4BTq6P5XLZY.exe"] = "45psrewIRS"
passcode["iJO15JsCa1bV5anXnZ9dTC9iWbEDmdtf.exe"] = "2LUmPSYdxDcil"
passcode["IXITujCLucnD4P3YrXOud5gC7Bwcw6mr.exe"] = "aGUwVeVZ2c19mgE"
passcode["JIdE7SESzC1aS58Wwe5j3i6XbpkCa3S6.exe"] = "goTZP4go"
passcode["jJHgJjbyeWTTyQqISuJMpEGgE1aFs5ZB.exe"] = "9aIZjTerf0"
passcode["JXADoHafRHDyHmcTUjEBOvqq95spU7sj.exe"] = "jZRmFmeIchneGS"
passcode["K7HjR3Hf10SGG7rgke9WrRfxqhaGixS0.exe"] = "Z8VCO7XbKUk"
passcode["kGQY35HJ7gvXzDJLWe8mabs3oKpwCo6L.exe"] = "14bm9pHvbufOA"
passcode["lk0SOpnVIzTcC1Dcou9R7prKAC3laX0k.exe"] = "9eDMpbMSEeZ"
passcode["MrA1JmEDfPhnTi5MNMhqVS8aaTKdxbMe.exe"] = "auDB6HtMv"
passcode["NaobGsJ2w6qqblcIsj4QYNIBQhg3gmTR.exe"] = "C446Zdun"
passcode["P2PxxSJpnquBQ3xCvLoYj4pD3iyQcaKj.exe"] = "nLSGJ2BdwC"
passcode["PvlqINbYjAY1E4WFfc2N6rZ2nKVhNZTP.exe"] = "0d7qdvEhYGc"
passcode["SDIADRKhATsagJ3K8WwaNcQ52708TyRo.exe"] = "5O2godXTZePdWZd"
passcode["SeDdxvPJFHCr7uoQMjwmdRBAYEelHBZB.exe"] = "ohj5W6Goli"
passcode["u3PL12jk5jCZKiVm0omvh46yK7NDfZLT.exe"] = "4z0gAyKdk"
passcode["u8mbI3GZ8WtwruEiFkIl0UKxJS917407.exe"] = "r6ZWNWeFadW"
passcode["v6RkHsLya4wTAh71C65hMXBsTc1ZhGZT.exe"] = "dEDDxJaxc1R"
passcode["w3Y5YeglxqIWstp1PLbFoHvrQ9rN3F3x.exe"] = "HQG0By9q"
passcode["wmkeAU8MdYrC9tEUMHH2tRMgaGdiFnga.exe"] = "0rhvT5GX"
passcode["x4neMBrqkYIQxDuXpwJNQZOlfyfA0eXs.exe"] = "Fs3Ogu6W3qk59kZ"
passcode["xatgydl5cadiWFY4EXMRuoQr22ZIRC1Y.exe"] = "8V9AzigUcb2J"
passcode["xyjJcvGAgswB7Yno5e9qLF4i13L1iGoT.exe"] = "gNbeYAjn"
passcode["y77GmQGdwVL7Fc9mMdiLJMgFQ8rgeSrl.exe"] = "8Etmc0DAF8Qv"
passcode["zRx3bsMfOwG8IaayOeS8rHSSpiRfc9IB.exe"] = "XgkvZJKe"

def run_binary(filename):
    code = passcode[filename]
    print("{} => {}".format(filename, code))
    p = Popen([filename,], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
    output = p.communicate(input=code)[0]
    print("output: {}".format(output))

for _, _, files in os.walk("."):
    for f in files:
        if f.endswith(".exe"):
            run_binary(f)

最后就能拿到flag

总结

这个是国外前几年的一个ctf比赛的题,看起来还不错,学到很多逆向的知识,还是收获颇多的,现在在这里记录一下做题的笔记


举报

相关推荐

0 条评论