GACTF easyRe

1.关于smc自解码部分

  • 当smc自解码过程太过复杂时,ida脚本反倒使用时间多,不如dump下来
  • 不是每道题都直接能看到字节数组的,反而你应该发现 一堆数字夹在代码与代码之间。
  • 粗心大意,没把smc过的dump过来导致浪费大量时间

几种dump的办法

  • ida动态调试 写脚本将其dump下
  • gdb 下断点同样调试 使用dump的命令
  • 都是动调dump,只是dump方式不同

easyRe1已经smc过。

vm函数 ret sp改为0(这是操作不够完美才出现得瑕疵)

之后便是对opcode的分析了。

动态调试方法

这些内容已经很详细了。

可能是栈数组:byte_804B080   栈数组里边 0x80 0x2 是一个过渡用的。并不会造成影响

mov     eax, [ebp-2Ch]
mov     eax, [eax+20h]
movzx   eax, byte ptr [eax]  ;这部分操作是一样的,取栈数组里的值,之后根据栈数组的值进行比较
or:
mov     eax, [ebp+var_2C]
mov     eax, [eax+20h]
movzx   eax, byte ptr [eax]

08331008 


mov     eax, [ebp-2Ch]
mov     eax, [eax+20h]  ; 回到数组中
lea     edx, [eax+1]    ; 使得下一次取到下一条指令

printf("%p") //输出结果为指针

.text:08048838
.text:08048DE1 retn


mov     eax, [ebp+var_2C]   ;固定地址 097B3008
mov     edx, [eax+4]        ;
mov     eax, [ebp+var_2C]
mov     eax, [eax+24h]

putchar--输出字符
0804b28c


unsigned char ida_chars[] =
{
    9,  16, 128,   2,  13,   0,   0,   0,  34, 119, 
   16, 128,   2,   9,   0,   0,   0,  35, 128,   2, 
    0, 150, 243, 120,  49, 119,  16, 128,   2,  17, 
    0,   0,   0,  35, 128,   2,   0,   0, 212, 133, 
   49, 119,  16, 128,   2,  19,   0,   0,   0,  34, 
  119, 160,   9, 128,   2, 255,   0,   0,   0,  49, 
  128,   3,   2,   0,   0,   0,  67, 128,   2,  24, 
    0,   0,   0,  65, 164,   0,   0,   0,   9, 128, 
    2,   8,   0,   0,   0,  34, 128,   2, 255,   0, 
    0,   0,  49, 128,   5,   7,   0,   0,   0,  68, 
  128,   2,  33,   0,   0,   0,  65, 164,   1,   0, 
    0,   9, 128,   2,  16,   0,   0,   0,  34, 128, 
    2, 255,   0,   0,   0,  49, 128,   9, 187,   0, 
    0,   0, 119, 128,   2, 255,   0,   0,   0,  65, 
  164,   2,   0,   0,   9, 128,   2,  24,   0,   0, 
    0,  34, 128,   2, 255,   0,   0,   0,  49, 128, 
    4, 160,   0,   0,   0,  66, 128,   2, 119,   0, 
    0,   0,  65, 164,   3,   0,   0, 161, 193,   0, 
  177, 119, 194,  11,   1,   0,   0, 193,   1, 178, 
  119, 194, 122,   0,   0,   0, 193,   2, 180, 119, 
  194, 149,   0,   0,   0, 193,   3, 179, 119, 194, 
    6,   1,   0,   0, 193,   4, 178, 119, 194, 125, 
    0,   0,   0, 193,   5, 180, 119, 194, 173,   0, 
    0,   0, 193,   6, 177, 119, 194,  47,   1,   0, 
    0, 193,   7, 179, 119, 194, 101,   1,   0,   0, 
  193,   8, 177, 119, 194,  45,   1,   0,   0, 193, 
    9, 177, 119, 194,  47,   1,   0,   0, 193,  10, 
  179, 119, 194,  57,   1,   0,   0, 193,  11, 179, 
  119, 194,  13,   1,   0,   0, 193,  12, 180, 119, 
  194, 187,   0,   0,   0, 193,  13, 178, 119, 194, 
    8,   0,   0,   0, 193,  14, 179, 119, 194,  13, 
    1,   0,   0, 193,  15, 177, 119, 194,  63,   1, 
    0,   0, 193,  16, 179, 119, 194,  58,   1,   0, 
    0, 193,  17, 179, 119, 194,  97,   1,   0,   0, 
  193,  18, 178, 119, 194,  87,   0,   0,   0, 193, 
   19, 177, 119, 194,  32,   1,   0,   0, 193,  20, 
  179, 119, 194,  13,   1,   0,   0, 193,  21, 177, 
  119, 194,  63,   1,   0,   0, 193,  22, 179, 119, 
  194,  63,   1,   0,   0, 193,  23, 180, 119, 194, 
  181,   0,   0,   0, 193,  24, 177, 119, 194,  19, 
    1,   0,   0, 193,  25, 180, 119, 194, 160,   0, 
    0,   0, 193,  26, 177, 119, 194,  33,   1,   0, 
    0, 193,  27, 179, 119, 194,  13,   1,   0,   0, 
  193,  28, 178, 119, 194,  11,   0,   0,   0, 193, 
   29, 179, 119, 194,  57,   1,   0,   0, 193,  30, 
  177, 119, 194, 115,   1,   0,   0, 193,  31, 178, 
  119, 194,  70,   0,   0,   0, 153
};


经过计算的值,再进行下一次计算时,是放在edx的

操作码说明
0x9:a1[1] = input;
0x16:a1[9] = a1[1];
0x80:略过,没有影响。
0x22:a1[1] >> = a1[2]  ; a1[2] = 13
0x77:a1[1] ^= a1[9]    ; a1[9] = 输出时的a1[1]
0x10:a1[9] = a1[1]       ; a1[1]计算之后出来的值又放至a1[9]
0x23:a1[1] << = a1[2]  ; a1[2] = 9
0x31:a1[1] &=a1[2]       ; a1[2] = 0x78F39600
0x77:a1[1] ^a1[9]      ; a1[9] = 0x10后的a1[9]
0x10:a1[9] = a1[1]       ; 
0x23:a1[1] << a1[2]       ; a1[2] = 17
0x31:a1[1] &=a1[2]       ; a1[2] = 0x85D40000
0x77:a1[1] ^a1[9]       ;
0x10:a1[9] = a1[1]       ;
0x22:a1[1] >>=a1[2]       ;a1[2] = 19
0x77:a1[1] ^a1[9]       ;
0xA0:a1 ==? 653840640  ;最终值是否等于653840640,不等于则退出
-----------------------------------------------------------
0x0862900C:[eax+4]的地址,存的是最终结果
mov     ds:dword_804B2A0[eax*4], edx;存了14C->0x41后的结果
----------------------------------------------------------
未知内容-a1[1]  a1[9]->该值是否是上边的计算结果?
0x9:input                ; 同样是上边的输入  0xFFE8BC9A
0x31:a1[1] & 0xff       ;&a1[2]
0x43:a1[1] * 0x08629008 ;*a1[3] 乘法  == 0x134
0x41:a1[1] + 0x18
0xA4:存a1[1]


下一个input开始
0x9:input
0x22:input >> 0x8       ; 
0x31:input & 0xFF       ;这两步结合起来应该是 取3,4处,前边那里是取1,2处
0x44:input / 0xBC       ;除法,没错的话,此时的input是7,结果为1A
0x41:input + 0x21        ;加法 
0xA4:存

下一个input开始
0x9:input
0x22:input >> 0x10         ;
0x31:input & 0xFF       ;这两步结合起来应该是 取 5 6处
0x77:input ^ 0xBB        ;
0x41:input + 0xff       ; 
0xA4:存

下一个input开始
0x9:input
0x22:input >> 0x18
0x31:input & 0xff        ;取 7 8 处
0x42:input - 0xA0       ;
0x41:input + 0x77       ;
0xA4:存


再之后:
0xA1:print("flag:")        ;长度为33的
0xC1:取输入的flag
0xB1:取前边4个计算结果
0x77:flag的每一位分别与四个中的一个^计算
0xC2:比较。与一个地方的值比较

0xC1:取flag
0xB2:取前边结果的第二个    ;B1 B2 B3 B4分别是四个前边的值
0x77:^
0xC2:

0xC1:取flag
0xB4:                    ;貌似不是按顺序的    cmp :0x95 0x106  .data:0804B164 db 0ADh  相差八位取值
应该使用脚本提取B1/2/3/4的顺序。也用脚本提取最终的比较值 题目就能完成了

Decompilation failure:
8048838: stack frame is too big

Please refer to the manual to find appropriate actions

[stack]:FFA80898->可能这个地址

byte_804B2E0放的是输入

 

mov     eax, [ebp-2Ch]
mov     eax, [eax+20h]
add     eax, 1       
movzx   eax, byte ptr [eax]  
movzx   eax, al
mov     [ebp-14h], eax  
mov     eax, [ebp-14h]     ;为什么这两步要再一次换来换去呢?
add     eax, 804B2E0h      ;取数据
movzx   eax, byte ptr [eax]
movzx   edx, al               ;取完放入edx中
mov     eax, [ebp-2Ch]
mov     [eax+4], edx       ;再放入[eax+4]中  是flag


mov     edx, ds:dword_804B2A0
mov     eax, [ebp-2Ch]
mov     [eax+24h], edx        ;取前边的4个计算结果 放入[eax+24h]

[0x14C, 0x3B, 0x152, 0x0D6]   dword_804B2A4->这是前边的4个计算结果


.data:0804B134 db 0B1h  ;B的起始地址

[stack]:FFF2BD68 db  0Bh  比较的值的起始地址 还有下一个要取 牛逼 是4字节的
.data:0804B137 db  0Bh
.data:0804B138 db    1     ; 真正的地址

.data:0804B140 db  7Ah ; z ; 下一个地址 相差0x9
.data:0804B141 db    0

.data:0804B149 db  95h
.data:0804B14A db    0
------------------------
addr = 0x804B134
for i in range(0,34):
    print(hex(Byte(addr)))
    addr +=0x9
    
print("====")            
# 跑B的脚本
0xb1
0xb2
0xb4
0xb3
0xb2
0xb4
0xb1
0xb3
0xb1
0xb1
0xb3
0xb3
0xb4
0xb2
0xb3
0xb1
0xb3
0xb3
0xb2
0xb1
0xb3
0xb1
0xb3
0xb4
0xb1
0xb4
0xb1
0xb3
0xb2
0xb3
0xb1
0xb2

------------

addr = 0x804B137
for i in range(0,32):
    print(hex(Word(addr)))
    addr +=0x9
print("=")
# 跑比较值的脚本
--------------------------------

0x10bL
0x7aL
0x95L
0x106L
0x7dL
0xadL
0x12fL
0x165L
0x12dL
0x12fL
0x139L
0x10dL
0xbbL
0x8L
0x10dL
0x13fL
0x13aL
0x161L
0x57L
0x120L
0x10dL
0x13fL
0x13fL
0xb5L
0x113L
0xa0L
0x121L
0x10dL
0xbL
0x139L
0x173L
0x46L

 

"""
1.smc操作--smc操作用dump操作做的。把代码winhex改了整上去。但是由于我整的代码是smc过后的那部分。
    因此,我每次动态调试,会把代码再次smc,导致hex变了,代码变了,程序就不行了。
    所以,1.动态调试出问题时,应该让程序run到结束,这样才能恢复原样
         2.dump时应该把smc计算那部分也dump掉?不一定。
    天津核那题 并没有进行动调,所以没有这问题。
2.虚拟机操作:
    通过一个个字节码,分为了三部分的操作:
        2.1 输入一个值,经过一系列计算后,等于某个值。使用z3求解。
        2.2 该值分为4部分,各自进行计算。得出四个中间值,用于后边的计算。
        2.3 进行flag的输入。对输入的flag进行计算。最终与其中的一些字节码比较。得出结果

    很多数据 比如 最终比较的值,中间值的选择,我都直接用idapython提取出来了。
3.模拟执行的办法 要实现。
"""
from z3 import *
s = Solver()
a = BitVec("a", 34)
print(type(a))

a ^= (a >> 13)
a ^= (a << 9) & 0x78F39600
a ^= (a << 17) & 0x85D40000
a ^= a >> 19
s.add(a == 0x26F8D100)

print(s.check())
m = s.model()
print(m)
[a = 4293442714]


# print("".join(list(map(chr, range(ord('a'), ord('z') + 1))))+"abcdefg")
# print(len("abcdefghijklmnopqrstuvwxyzabcdef"))

tmp = [0x14C, 0x3B, 0x152, 0x0D6]

# 取

B = [0x1,0x2,0x4,0x3,0x2,0x4,0x1,0x3,0x1,0x1,0x3,0x3,0x4,0x2,0x3,0x1,0x3,0x3,0x2,0x1,0x3,0x1,0x3,0x4,0x1,0x4,0x1,0x3,0x2,0x3,0x1,0x2]
# [0xb1,0xb2,0xb4,0xb3,0xb2,0xb4,0xb1,0xb3,0xb1,0xb1,0xb3,0xb3,0xb4,0xb2,0xb3,0xb1,0xb3,0xb3,0xb2,0xb1,0xb3,0xb1,0xb3,0xb4,0xb1,0xb4,0xb1,0xb3,0xb2,0xb3,0xb1,0xb2]
print(len(B))

fin = [0x10b,0x7a,0x95,0x106,0x7d,0xad,0x12f,0x165,0x12d,0x12f,0x139,0x10d,0xbb,0x8,0x10d,0x13f,0x13a,0x161,0x57,0x120,0x10d,0x13f,0x13f,0xb5,0x113,0xa0,0x121,0x10d,0xb,0x139,0x173,0x46]
print(len(fin))
# for i in range(len(B)):
#    print(tmp[B[i] - 1])
for i in range(len(B)):
    fin[i] ^= tmp[B[i] - 1] # tmp的范围是[0,3] 但B的范围是从1开始的,是[1,4]
for i in fin:
    print(chr(i),end="")
# print(fin)

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值