一个自制高强度 KeygenMe,高手大佬来试试,1周内第1个完成keygen者奖500CB,不要错过
本帖最后由 solly 于 2020-8-24 15:06 编辑一个自制高强度 KeygenMe,无壳,无虚,无反,无混,原生vs2017编译,算法流程来自本人以前破解的一个小软件,不过经过了轻量级地魔改,高手大佬们来试试,1周内第1个完成keygen者奖500CB,看看能不能撑过1周时间,大佬们不要错过哦。
{:1_918:}
界面和成功截图:
本帖最后由 monvvv 于 2020-8-26 15:34 编辑
直接IDA F5硬上(虽然有些循环被unroll了)费了亿点点时间搞好了。没怎么弄过Win32 App,有一半时间都花在了理解流程上。。。数据流:
```mermaid
sequenceDiagram
participant Group
participant Button
participant Button2
opt LBUTTONDOWN
Button2 -->> Group: Save username to WindowText
Note right of Button2: Cook mid_pwd with raw password
Button2 ->> Button: Call proc
Note right of Button: Cook raw_data<br>with mid_pwd and username
end
opt LBUTTONUP
Button ->> Group: WM_COMMAND 0xCE7
note right of Group: Cook data with raw_data
note right of Button: Check and remove tail
Button -->> Group: Save data to WindowText
Button ->> Group: WM_COMMAND 0xCE5
note right of Group: Check data and set to label
end```
加密:
from ctypes import c_uint32
from utils import *
def parse_sn(sn):
v = []
for p in sn.split('-'):
b = bytes.fromhex(p)
assert len(b) == 4
v.extend(b)
return v
def cook_raw_sn(sn):
def f(a): return ((a ^ sn[-2]) + sn[-1]) & 0xFF
sn = list(sn)
k = chain(map(f, sn[:22]), sn[-2:])
return k
def process_mid_sn(sn):
MAGIC_KEY =
# TEA-like encrypt
def process_block(a, b):
delta = 0x61C88647
a = c_uint32(a)
b = c_uint32(b)
s = c_uint32(0)
for _ in range(32):
s.value -= delta
a.value += (s.value ^ (b.value >> 5)) + \
MAGIC_KEY + (MAGIC_KEY ^ b.value) + (b.value << 4)
b.value += (s.value ^ (a.value >> 5)) + \
MAGIC_KEY + (MAGIC_KEY ^ a.value) + (a.value << 4)
return a.value, b.value
t = uint32s_to_bytes(chain(
*map(lambda ns: process_block(ns, ns), grouper(2, bytes_to_uint32s(sn)))))
return t
def cook_username(username):
MAGIC = b'c0DebY SOLLY'
k = crc(username.encode()) + \
int.from_bytes(MAGIC, 'little') + \
int.from_bytes(MAGIC, 'little')
return k & 0xFFFFFFFF
def mix_sn_and_username(username, sn):
k = cook_username(username)
delta = 0x76BDEFDB
s = c_uint32(0)
k = c_uint32(k)
l = []
for v in bytes_to_uint32s(sn):
k.value -= delta
# Reverse bytes
k.value = int.from_bytes(k.value.to_bytes(4, 'big'), 'little')
s.value = (s.value ^ v) + k.value
l.append(s.value)
return uint32s_to_bytes(l)
def process_data(data):
MAGIC_KEY = [
0x65A04939, 0x51B194D7, 0xE288C9D9,
0x077FBB77, 0xFD05CDF1, 0xA399B665
]
v = for i, v in enumerate(bytes_to_uint32s(data))]
return uint32s_to_bytes(v)
def check(data):
data = list(data)
assert len(data) == 24
ints = list(bytes_to_uint32s(data))
if ints[-2] == 0:
return False
if ints[-2] ^ ints[-1] != 0xFFFFFFFF:
return False
if not bytes(data)[:16].decode('gbk').startswith('成'):
return False
return True
if __name__ == "__main__":
username = '123456'
sn = '95E11821-1C4A3FFE-7E978C5E-259DFD9B-BAD811D0-D6A75D31'
raw_sn = parse_sn(sn)
mid_sn = cook_raw_sn(raw_sn)
final_sn = process_mid_sn(mid_sn)
data = mix_sn_and_username(username, final_sn)
final_data = process_data(data)
print(check(final_data))
由于最后的检测太宽松导致存在多解。
解密:
from utils import *
from ctypes import c_uint32
TARGET_DATA = list(chain('成功了,好牛逼!'.encode(
'gbk'), b'\xFF\xFF\xFF\xFF\x00\x00\x00\x00'))
def decode_data(data):
MAGIC_KEY = [
0x65A04939, 0x51B194D7, 0xE288C9D9,
0x077FBB77, 0xFD05CDF1, 0xA399B665
]
v = for i, v in enumerate(bytes_to_uint32s(data))]
return uint32s_to_bytes(v)
def cook_username(username):
MAGIC = b'c0DebY SOLLY'
k = crc(username.encode()) + \
int.from_bytes(MAGIC, 'little') + \
int.from_bytes(MAGIC, 'little')
return k & 0xFFFFFFFF
def extract_sn_from_data(username, data):
k = cook_username(username)
delta = 0x76BDEFDB
s = c_uint32(0)
k = c_uint32(k)
l = []
for v in map(c_uint32, bytes_to_uint32s(data)):
tmp = v.value
k.value -= delta
# Reverse bytes
k.value = int.from_bytes(k.value.to_bytes(4, 'big'), 'little')
v.value -= k.value
v.value ^= s.value
s.value = tmp
l.append(v.value)
return uint32s_to_bytes(l)
def decode_final_sn(sn):
MAGIC_KEY =
# TEA-like decrypt
def process_block(a, b):
delta = 0x61C88647
# 0XC6EF3720 is `s`'s final value in encryption
s = c_uint32(0XC6EF3720)
a = c_uint32(a)
b = c_uint32(b)
for _ in range(32):
b.value -= (s.value ^ (a.value >> 5)) + \
MAGIC_KEY + (MAGIC_KEY ^ a.value) + (a.value << 4)
a.value -= (s.value ^ (b.value >> 5)) + \
MAGIC_KEY + (MAGIC_KEY ^ b.value) + (b.value << 4)
s.value += delta
return a.value, b.value
# ####
t = uint32s_to_bytes(chain(
*map(lambda ns: process_block(ns, ns), grouper(2, bytes_to_uint32s(sn)))))
return t
def decode_mid_sn(sn):
sn = list(sn)
def f(a): return ((a - sn[-1]) & 0xFF) ^ sn[-2]
k = chain(map(f, sn[:22]), sn[-2:])
return k
def sn2str(sn):
def to_hex(it): return bytes(it).hex().upper()
s = str.join('-', map(to_hex, grouper(4, sn)))
return s
if __name__ == "__main__":
username = '52pojie.cn'
data = decode_data(TARGET_DATA)
final_sn = extract_sn_from_data(username, data)
mid_sn = decode_final_sn(final_sn)
sn = decode_mid_sn(mid_sn)
print(sn2str(sn))
本帖最后由 solly 于 2020-8-26 23:05 编辑
monvvv 发表于 2020-8-26 15:30
直接IDA F5硬上(虽然有些循环被unroll了)费了亿点点时间搞好了。没怎么弄过Win32 App,有一半时间都花在 ...
python不熟,但看了看应该没有错,是正确的了。
这个 keygenme 主要还是考查对 windows api 及其消息回调机制的掌握,加密是用的原发贴中公开的,没有改动(查特征魔数就可确定哪几个过程,并且方便下断点),还减少了几个过程,只改动了密码。
所以只要理解了我设定的数据流程后,就可以很快解出来。
最后多解是因为没有对后两段的CRC值进行检查了,只要异或值是-1就可以了。
500CB送给你。
补充一下:
1、搞不清流程的,只要在IDA中查看一下,把前十几个函数的入口都下一个断点,就很快可以确定数据流程了。
2、发现直接使用带A和W的API函数对,如的SetXXXA和GetXXXW,可以隐式完成字符串内码转换。 如果是Crackme你这都提供了一组码了,最笨的办法是一个个试你屏蔽的那一段,总能试出来,
但你这个是KeygenMe,那就要研究你的算法了,无壳,无虚,无反,无混那必然就是很恶心的一大串连环算法,各种移位XOR换算,没那精力研究,支持一下,期待有大神来搞定这个。 技术上比不过 但是我ID绝对秒杀你们 哈哈:keai 拿魔数搜出来了:https://www.52pojie.cn/thread-1081400-1-1.html monvvv 发表于 2020-8-24 22:21
拿魔数搜出来了:https://www.52pojie.cn/thread-1081400-1-1.html
对,就是这个的轻量级魔改,你可以试试。。。。。。 本帖最后由 a38758720 于 2020-8-25 11:10 编辑
晚上下载一下试试,刚看了之前lz破解的那个帖子,大佬行为。 要不起,下一个 小白路过支持一下 路过给大佬点个赞 对于双递归都研究不明白的我,只能看看
页:
[1]
2