keygen-me-1 picoCTF 题解

本题来自picoCTF2018

题目描述

Can you generate a valid product key for the validation program in /problems/keygen-me-1_3_a2370158b7b72b3863212502340f2c32

解题思路

首先用file查一下文件信息,32位elf可执行文件。

在这里插入图片描述
放到虚拟机里面,加上可执行权限,运行一下。

在这里插入图片描述

可以看到要求输入16个字符的key。

用IDA查看一下伪代码,可以直接在左边的函数窗口找到main函数,或者通过字符串的交叉引用找到main函数,然后F5查看伪代码.

在这里插入图片描述

可以看到有两个关键的函数,check_valid_keyvalidate_key,这两个函数对你的输入进行了检测。

我们首先来看check_valid_key函数。

在这里插入图片描述

里面有一个check_valid_char函数进行检查每一个字符,每一个字符的ascii要求在指定范围内,翻译过来就是由数字和大写字母组成

在这里插入图片描述

check_valid_key的功能出来了,就是验证你的输入是否合法(是否由数字和大写字母组成)。

validate_key函数如下图,也比较简单,v2是一个s的前15位进行运算然后累加的和,最后比较v2%0x24ord(s[15])的值是否相等。注意有一个ord函数,这个函数不是python中的ord函数,是他自己定义的一个函数。

在这里插入图片描述

ord函数也比较简单,如果a1是数字(也就是ascii码在48到57之间)就返回a1-48,否则返回a1-55,字符串在C中都是以ascii码的形式存储的,所以能够与数字直接进行运算。

在这里插入图片描述

由于这个逻辑比较简单,我们可以手动算一个key,比如,前15位我都让他为数字0,那么ord(s[i])返回到值为0v2的计算方式如下面的代码。

for(int i=0; i<15; i++){
  	v2 += 1 * (i + 1)
}

v2 = 1+2+3+4+5+6+7+8+9+10+11+12+13+14+15 = 120,然后模除以0x24 等于

12,然后找一个大写字母,让ord(s[15])的值等于12就行,逆着推一下,12+55=67,大写字母C。最后构造出来的key为000000000000000C

输入正确的key,提示成功,但是没有flag,因为需要通过ssh连接上题目的服务器,在服务器上运行才能读取flag文件。

在这里插入图片描述

解题脚本

最后补充一个脚本,通过Z3来解这道题,大家有兴趣的话可以看一下。

# -*- coding: utf-8 -*
from z3 import *

a1 = [Int('a1_%d' % i) for i in range(16)]
s = Solver()
ord = lambda x: If(And(x > 47, x <= 57), x - 48, x - 55)
for i in range(16):
    s.add(Or(And(a1[i] > 0x2f, a1[i] <= 0x39), And(a1[i] > 0x40, a1[i] <= 0x5a)))

v2 = Sum([(ord(a1[i]) + 1) * (i + 1) for i in range(15)])
v2 %= 0x24
print(v2)
s.add(v2 == ord(a1[15]))
if s.check() == sat:
    m = s.model()
    flag = ''
    for i in range(16):
        flag += chr(m[a1[i]].as_long())
    print(flag)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值