170818 逆向-南邮CTF(WxyVM2)

1625-5 王子昂 总结《2017年8月18日》 【连续第320天总结】
A. 南邮CTF-WxyVM2
B.
上次没做完的正巧在52破解论坛上看到有人发问了,就摸过来再做做看
跟WxyVM1比较像,不过感觉这题相比VM来说更像花指令~
首先看源码分析,先验证长度为25,然后进行了一大片的加减异或操作,最后与内存中的一个字符串进行比较
上次乍一看大片的加减异或操作不好处理,也没想到怎么将指令dump下来逆操作
这次仔细的分析一下发现大部分的操作都是无意义的:
这里写图片描述
仔细观察,输入在0x694100处,单位为byte,长度为25
也就是说,输入的字符串固定在0x694100-0x694118内,大片的dword操作都是超出这个范围的,它们没有意义
最后的比较字符串位于0x694060处,单位为dword,长度为25,是不变的字符串,直接IDC脚本dump出来即可
那么关键在于如何提取有意义的操作:
我是直接全选IDC反编译出来的命令,掐头去尾,以“;”作为分隔符得到命令集合的列表,然后分析特征:无意义的操作开头为dowrd,所需要的操作开头为byte(另外还有一些自加自减操作需要另外处理)
遍历列表,将有意义的保存下来,然后再分析提取被操作数(即下标)、操作命令和操作数
确认正向测验的脚本结果与动态调试中所查看到的内存无误,说明思路和脚本都正确,将命令加减颠倒,处理字符串改为直接dump出来的结果即可
附上python脚本:


def arr(list, s):  # 分析字符串,将被操作数、命令、操作数分别放入数组
    tmp = [0, ‘’, 0]
    tmp[0] = int(s[9], 10) * 16 + int(s[10], 16)#被操作数下标
    tmp[1] = s[12]#操作符
    tmp[2] = s[15:]#操作数
    if (len(tmp[2]) == 0):#提取失败,为自增/减类型(++byte_xxx型)
        tmp[0] = int(s[11], 10) * 16 + int(s[12], 16)
        # print(i,tmp[0])
        tmp[1] = s[0]
        tmp[2] = '1'
    if (tmp[2][0] is '0'):#操作数为十六进制
        tmp[2] = int(tmp[2][2:-1], 16)
    else:
        if (tmp[2][-1] is 'u'): tmp[2] = tmp[2][:-1]#操作数末尾去除'u'
        tmp[2] = int(tmp[2], 10)
    list.append(tmp)


def positive(list):#正向操作函数
    ori = input("Please input the flag(25):")
    flag = []
    # 提取ASCII并进行操作
    for i in ori:
        flag.append(ord(i))

    for i in list:
        n = flag[i[0]]
        if (i[1] is '+'):
            n = n + i[2]
        if (i[1] is '-'):
            n = n - i[2]
        if (i[1] is '^'):
            n = n ^ i[2]
        flag[i[0]] = n % 256#操作单位为字节,解决溢出

    return flag


def negative(list, ori):#逆向还原函数
    flag = ""

    for i in list[::-1]:
        n = ori[i[0]]
        if (i[1] is '+'):
            n = n - i[2]
        if (i[1] is '-'):
            n = n + i[2]
        if (i[1] is '^'):
            n = n ^ i[2]

        ori[i[0]] = n % 256

    for i in ori:
        flag = flag + chr(i)

    return flag

#operator为IDA反编译出的全部命令
o = operator.split(";")#分割命令形成列表
operators_str = []#初步有效命令列表
operators_com = []#最终分析命令列表

#内存中dump出来的,0x401060的结果
ori = [0xffffffc0, 0xffffff85, 0xfffffff9, 0x6c, 0xffffffe2, 0x14, 0xffffffbb, 0xffffffe4, 0xd, 0x59, 0x1c, 0x23,
       0xffffff88, 0x6e, 0xffffff9b, 0xffffffca, 0xffffffba, 0x5c, 0x37, 0xffffffff, 0x48, 0xffffffd8, 0x1f, 0xffffffab,
       0xffffffa5]

# 去除混淆命令和开头的换行、空格符号
for i in o[:-1]:
    if (i[3] is not 'd'):
        operators_str.append(i[3:])
# 分析
for i in operators_str:
    arr(operators_com, i)

# positive(operators_com)
print(negative(operators_com, ori))

C. 明日计划
NATAS

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值