逆向分析——2022KCTF秋季赛第六题详解

本文介绍了一道CTF题目中程序的逆向分析过程,并详细解释了如何通过IDA Pro进行逐步分析,最终利用暴力破解的方式找到正确的14位字符串答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

刚入门逆向试着复现一道CTF题,大佬们的文章省去了一些步骤(作者太菜了…),在这里记录详细的步骤。
题目链接: link
解析链接:link


一、程序分析

先运行程序记下出现的字符串:“please input”、“error”

拖到IDA里去看看,作者的版本为"IDA pro 7.0",程序逻辑比较简单,输入一个字符串,经过一系列运算输出“success”或"error"。
程序整体结构输入程序段
输出程序段
现在从头开始分析,先F5一下,找到第一个跳转到"error"的函数sub_401000返回值必须为14。

点进去是个递归函数,变量result和地址a1不停自增直到a1指向的值为0,便分析出函数作用为得到参数的位数,因此输入的字符串位数为14.
在这里插入图片描述
继续往下分析,根据最后的程序能得出v23是个判断变量且不能为0,所以必须条件必须为true,srand(v4)是初始化函数,通过_getptd()[5]将输入与rand()相关联,unk_40F000的数据必须等于rand()函数返回的值,且该数据必须大于unk_40F050的数据(但题解并没有管这个条件)。下面还有一段程序是重复上面的过程。
在这里插入图片描述
再往下这里有个小技巧把v24比较值用字符显示可得出"KCTF"
在这里插入图片描述
最终分析出的信息为输入14位字符串包含两个5位数和"KCTF",可以推测"KCTF"位于两个数的中间,格式为“XXXXXKCTFXXXXX",5位数通过rand()运算必须分别等于unk_40F000和unk_40F050的数据。“XXXXXKCTFXXXXX".

二、暴力破解

代码为上述链接作者的代码:

'''
作者:htg.心学
'''
seed = 0
###初始化种子
def InitSand(sd):
    global seed
    seed = sd
###获取随机值
def GetSand():
    global seed
    seed = seed * 0x343FD
    seed = seed & 0xFFFFFFFF
    seed = seed + 0x269EC3
    seed = seed & 0xFFFFFFFF
    returnValue = seed >> 0x10
    returnValue = returnValue & 0x7FFF
    return returnValue
###两个列表
preList = [0x00003BFC,0x00002173,0x000025BB,0x0000380B,0x00002C13,0x000075BE,0x00007366,0x000046A3,0x000013C1,0x0000159B,0x00005B5F,0x0000534F,0x00004E37,0x00003A04,0x00001301,0x00005D0C,0x00004155,0x000048E9,0x000061D2,0x00006158]
sufList = [0x00002BB6,0x00006B5A,0x000003D4,0x0000152B,0x00006E04,0x0000254C,0x000040AE,0x000056CA,0x000017E1,0x000055C7,0x00003641,0x00002D3C,0x00000A41,0x00004BC5,0x00006233,0x00001FE7,0x00006E05,0x00000F6E,0x00006398,0x00006AD7]
######三部分:XXXXXKCTFYYYYY
preFound = False
sufFound = False
print("寻找第一部分......")
for i in range(10000, 100000):
    InitSand(i)
    preFound = True
    for a in preList:
        if GetSand() != a:
            preFound = False
    if preFound:
        print("\t找到第一部分:{:05}".format(i))
        break
if not preFound:
    print("Failed!")
###########################################################
print("寻找第三部分......")
for j in range(100000):
    InitSand(j)
    sufFound = True
    for a in sufList:
        if GetSand() != a:
            sufFound = False
    if sufFound:
        print("\t找到第三部分:{:05}".format(j))
        break
if not sufFound:
    print("Failed!")
 
SN = "{:05}KCTF{:05}".format(i,j)
print("序列号:{}".format(SN))
###########################################################

关于上述代码,GetSand()函数与rand()函数相同,preList和sufList分别对应unk_40F000和unk_40F050。
在这里插入图片描述
最终得出结果为14725KCTF83690,程序运行如下图:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值