32 or 64

因为沙老师的题目。。。
//详情看上一篇blog
怎么说呢。。。写那题的时候我还在想为什么ida pro那么nb的工具会出现反编译错误这种低级问题
害得我看汇编
而且调试的时候也发现,汇编有点奇怪。。。
有时候几步一走,有些指令都没跑。
这篇blog我来说下对于32位程序中调用了64位的学习

参考链接

32-64之初体验

一开始我还不知道有这种骚操作
先看一下程序吧
题目是护网杯的
1
一眼过去啥也没有
查找字符串也只有俩sorry
运行一下程序看看
2
看到这就能猜到是smc了
下好断点开始单步调试
3
可以看到字符串是加密的,程序运行是对其解密
那段数据其实就是input_code
程序停在了输入段
可以看到下面就有个长度验证//猜测
大于18
看看下面的check
4
稍微看一下
//因为我是在中午休息的时候写这题的,只有20分钟时间写,然后就要去上课了。
其实不难啊
和hgame的很像
//太天真了,那时候我还没意识到什么32调用64
先看看check1
5
很简单,输入的前6个与0x22异或后再与上面的数据对比
解一下可以看到前6个字符是hwbctf
然后看看check2
6
不需多说
它还透露出俩个花括号内有11个字符
说明我们输入的字符数应该是19
看看最后一个check
7
问题就出在这
仔细看,其实只有10个被check了
难不成还有一个字符是随便输入?
和tamuctf的一样???
那这出题人也太没水平了吧//打死
照着反编译代码用z3写一下
显示unsat
我透???
难不成又要我手解???
初步看一下应该可以手解,但是有明显的矛盾
看看这三句

1
2
3
((unsigned __int8)(*(a1 - 1) ^ *(a1 - 1) ^ a1[1]) != 54)
((unsigned __int8)a1[8] + (unsigned __int8)a1[1] != 85)
(a1[8] != 53)

可以定出来a1[1],但是俩次解出来都是不一样
说明有问题
没办法
调试看汇编
问题马上就出来了
反编译出错了
其实应该是验证11个的
我们输入hwbctf{0123456789a}
这样更有利于定位check的下标
8
这些movzx eax, byte ptr [eax]
重点关注下
可以看到对应的下标
然后发现是反编译出错了
。。。
重新些脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# -*- coding: UTF-8 -*-
from z3 import *
s = Solver()
a = [BitVec('u%d'%i,8) for i in range(11)]
s.add(a[5] == 0x30)
s.add(a[10] == 0x35)
s.add((a[8] ^ a[6] ^ a[7]) == 0x60)
s.add((a[4] ^ a[2] ^ a[6]) == 0x77)
s.add((a[0] ^ a[1] ^ a[3]) == 0x36)
s.add(a[10] + a[3] == 0x55)
s.add(a[2] + a[9] == 0xdb)
s.add(a[5] + a[4] == 0x9e)
s.add(a[2] + a[1] + a[5] == 0xc4)
s.add(a[9] + a[7] + a[8] == 0xc2)
s.add(a[3] + a[5] + a[9] == 0xbe)
s.add(a[2] + a[6] + a[8] == 0x115)
s.add(a[1] + a[10] + a[7] == 0x7c)

flag = ''
if s.check() == sat:
result = s.model()
print s.model()
for i in range(11):
flag += chr(result[a[i]].as_long().real)
print flag
#1'm n0t 4n5

所以输入应该是hwbctf{1’m n0t 4n5}
感觉挺有趣的,因为好奇特别想知道这题是怎么出的?
他在考我们什么?
比较懵逼
然后问了下老师
据说是32位和64位的切换,那时候没注意哪来的64位
只是以为要看汇编
哎。。。。。。。。。
正巧又看到了一篇不错的文章也讲到了这题
//貌似还很新哟,最近的文章。
好了。
学习 start!!!

Let’s 深入32-64

首先讲的是区别,32位与64位的主要区别就在于cs
一个是0x23一个是0x33
但如何判断程序是否调用了64位呢?
文章中作者也写到了
靠的就是那个retf
retf吧栈中的0x33给了cs,由此来调用64位
9
我们可以看到有retf
还有0x33
说明下面就是开始64位了
调试的话也能发现程序有时候是几步一走的
那如何调试???
用gdbserver
10
//忽视我的背景
//才不是色图呢
然后照着文章写的去做
11
就ok啦
静态分析的话可以用py来dump

1
2
3
4
5
6
7
import idaapi
start_address = 0xDEAD000
data_length = 0xb0000-0xad000
data = idaapi.dbg_read_memory(start_address, data_length)
fp = open('C:\Users\AZX\Desktop\dump', 'wb')
fp.write(data)
fp.close()

也可以用作者的idc脚本

1
2
3
4
5
6
7
8
9
static main(void)
{
auto fp, begin, end, dexbyte;
fp = fopen("C:\father64.mem", "wb");
begin = 0xDEAD000;
end = 0xDEB0000;
for ( dexbyte = begin; dexbyte < end; dexbyte ++ )
fputc(Byte(dexbyte), fp);
}

然后放ida64里
12
这边就没有反编译错误了

小试牛刀

文章中附赠了资源,其中有win的题目
我来试一下吧
然后很成功的没写出来。。。
40min。。。
还是看作者的wp吧。。。
dump出来后看到很多什么memory就很懵逼
看完wp后发现这题果然超出我的认知范围了。。。
没办法
那就TODO吧

文章目录
  1. 1. 32-64之初体验
  2. 2. Let’s 深入32-64
  3. 3. 小试牛刀
|