s0i1 发表于 2021-11-17 20:13

2021鹤城杯-re-Petition

我一开始很好奇,它对栈顶数据的操作方式,因为没有单独出现,而是出现了、等这种偏移的访问方式,这个阻碍了我进一步的分析。。

动态调试下,对应的指令就直接是 :

scanf(""%63s", 0xffffd190)
此时 = 0xffffd190
此时,edi =

在0x402910里面,如果验证不正确,则最后的返回地址为start函数里的地址,如果正确,则为其他地址:

sub_402910 这个核心函数的逻辑为:
将传入参数与call指令下一个位置的地址相减,然后与dl相乘,再加回减去的地址,然后跳转到计算后的地址中
经过验证,当dl为1的时候,传入参数即可作为地址被调用成功。

esp_4 = 0x40119C
esp = 0x40117A
ret_addr = 0x40119C
#dl = ^ 0x0CC84881E) & 0xff)]
#ret_addr = (dl * ( - )) & 0xff +
temp1 = esp_4 - esp
print((ret_addr - esp)/temp1)

我没看懂的地方
官方题解说:
start函数中,只有一处向内存中写入1
而在这里,又将的值赋给了edx,再向下就是校验函数了。显而易见,我们的目的就是让程序在执行到xor byte ptr , 1这条指令时,让eax与edx相等。


于是有:
(esp ^ input ^ 0x0CC84881E) & 0xFF == esp ^ 0x3E ^ 0x46

input ^ 0x1E ==0x3E ^ 0x46
然后写脚本匹配,批量提取信息反推flag。
它的信息可能是指,如果你的输入是正确的,就会导致dl为1,输入错误就不能,应该是在xor edx, 这一步,将赋值给edx。它是怎么搞的我实在没看懂。

脚本
import idc
import idaapi
import idautils
import re


idaapi.auto_wait()

flag = ""

count = 0
for func in idautils.Functions():
    # Ignore Library Code
    flags = idc.get_func_flags(func) # 获取函数的标志,分为lib和普通函数等
    #print("flags: ", flags)
    if flags & FUNC_LIB: # 跳过系统函数
      continue
    instuction_generator = idautils.FuncItems(func) # <class 'generator'>
    instuction_list = list(instuction_generator)   
    len_list = len(instuction_list)
    opnd1 = 0
    opnd2 = 0
    opnd3 = 0
    for i,instruction in enumerate(instuction_list): # 当前函数中的每个指令地址      
      # 匹配指令 xor bl, 对应操作码 32 1E ; xor ebx, XXh 对应操作码81 F3 XX XX XX XX
      if idaapi.get_byte(instuction_list) == 0x32 and idaapi.get_byte(instuction_list+1) == 0x1E:
            if i+1 < len_list: # 防止越界访问
                if idaapi.get_byte(instuction_list) == 0x81 and idaapi.get_byte(instuction_list+1) == 0xF3:
                  opnd3 = idaapi.get_dword(instuction_list + 2)
                  print(hex(opnd3))
                  #count += 1
                  
      if i+1 < len_list:
            insText = idc.generate_disasm_line(instuction_list, 0) # 获取指令      
            nextInsText = idc.generate_disasm_line(instuction_list, 0) # 获取指令
            if "xor   eax," in insText and 'h' in insText and "xor   eax," in nextInsText and 'h' in nextInsText:
                opnd1 = idc.get_operand_value(instuction_list, 1)
                opnd2 = idc.get_operand_value(instuction_list, 1)
                print("opnd1: ", hex(opnd1))
                print("opnd2: ", hex(opnd2))            
                flag += chr(int((opnd3 ^ opnd1 ^ opnd2) & 0xFF))

print(flag)

题目文件:
Petition.zip


涛之雨 发表于 2021-11-18 07:06

部分图片插入错误,请查看帮助

46114 发表于 2021-11-18 13:55

很好,关注一波

tl;dr 发表于 2021-11-19 05:15

snake88 发表于 2021-11-19 08:44

终于找宝贝了

alk9000 发表于 2021-11-19 18:37

批量提取信息反推flag,非常舒适

klksH 发表于 2021-11-20 12:48

支持支持,撒花{:1_918:}

s0i1 发表于 2021-12-8 16:44

tl;dr 发表于 2021-11-19 05:15
鹤城在哪里?

河南省鹤壁市吧
页: [1]
查看完整版本: 2021鹤城杯-re-Petition