【160Crackme】《CrackMe_0006》

Crackme

Posted by Corax on November 16, 2023

CrackMe_0006

这题我看是四星难度,算法还是有的一玩的。

拿到程序看看

image-20231117183813427

无壳,直接OD里面看得了。

爆破

首先定位关键字符串

肯定是GOOD了

image-20231117184043890

追踪进来

看到正确回显上面有个jnz,把他改掉

image-20231117184127532

image-20231117184135466

跑跑看,是可以的。

image-20231117184208413

算法逆向

这个相对繁琐一些。

在这里读入name之后紧接着一个CALL,进去看看做了什么

image-20231117184331356

第一阶段

代码流程不长,但是有一个什么循环在里面,主要是ECX和add eax和edx两步。

我们简单跑两轮

image-20231117184505762

读入h,然后和1乘 和0相加存入eax

image-20231117184618406

读入y 和刚刚的结果想成 存入eax

image-20231117184655355

不过有个东西需要注意,这imul实际上是eax ^ ecx,然后如果超过32位,会存在edx,所以脚本如下

sName = "hyyyy"
nTemp = 1
nTemp1 = 0
nEnd1 = 0
sFlag = ""

for i in sName:
    nTemp = nTemp * ord(i)
    nTemp1 = nTemp & 0xffffffff
    nTemp2 = nTemp // 0xffffffff
    nEnd1 = nTemp1 + nTemp2

print("一阶段结果"+str(hex(nEnd1)))

在OD里跑出来

结果

image-20231117184854865

image-20231117184906665

OK

第二阶段

第二个阶段‘

又进入了一个call,进去看看

image-20231117184931821

是这样的,实际上就是上面的结果循环左移,但是要注意,这不是«这个左移,这个左移在末位补0,而rol是把高位出去的补到低位去,让GPT写个相同作用的脚本

image-20231117185010373

def rol(value, shift, bitsize=32):
    shift %= bitsize
    return ((value << shift) & (2**bitsize-1)) | (value >> (bitsize - shift))

#nEnd1 = nEnd1 << 1
nEnd1 = rol(nEnd1,1)

两边运行结果

image-20231117185152063

image-20231117185202753

ok的

第三阶段

第三阶段 出来之后,两个运算

image-20231117185307352

比较简单,实际上就是

先和0x7DAF15F8 逻辑或

再去掉最高位

nEnd1 = nEnd1 | 0x7DAF15F8
nEnd1 = nEnd1 & 0xfffffff

两边结果

image-20231117185517946

image-20231117185521842

ok

第四阶段

主要阶段来了

image-20231117185545751

还是比较纷杂的

最上面那个call

image-20231117185649103

目的其实是啥呢?感觉很多,但其实就是为了获取上面经过计算dbf3ffa的最低位a

出来了,答案与我们分析一致

image-20231117185740685

然后干啥呢,其实就是用这个a作为需要的位置然后取071362de9f8ab45c相应字符串添加进去而已

在进入下面的这个call

image-20231117190130632

这个函数是为了缩短dbf3ffa,变成dbf3ff。

然后一遍遍循环就是了

for i in range(100):
    nTemp3 = 0
    sKey = "071362de9f8ab45c"
    nTemp3 = nEnd1 & 0xf
    sFlag += sKey[nTemp3]
    #print("结果11ssa  "+str(hex(nTemp3)))
    nEnd1 = nEnd1 // 0x4
    if (nEnd1 == 0):
        break
    #print(hex(nEnd1))


print (sFlag)

就可以输出正确的serial了。

完整keygen

sName = "hyyyy"
nTemp = 1
nTemp1 = 0
nEnd1 = 0
sFlag = ""

for i in sName:
    nTemp = nTemp * ord(i)
    nTemp1 = nTemp & 0xffffffff
    nTemp2 = nTemp // 0xffffffff
    nEnd1 = nTemp1 + nTemp2

print("一阶段结果"+str(hex(nEnd1)))

def rol(value, shift, bitsize=32):
    shift %= bitsize
    return ((value << shift) & (2**bitsize-1)) | (value >> (bitsize - shift))

#nEnd1 = nEnd1 << 1
nEnd1 = rol(nEnd1,1)
#nEnd1 = nEnd1 & 0xffffffff
print ("移位后结果"+str(hex(nEnd1)))
nEnd1 = nEnd1 | 0x7DAF15F8
nEnd1 = nEnd1 & 0xfffffff
print (hex(nEnd1))

for i in range(100):
    nTemp3 = 0
    sKey = "071362de9f8ab45c"
    nTemp3 = nEnd1 & 0xf
    sFlag += sKey[nTemp3]
    #print("结果11ssa  "+str(hex(nTemp3)))
    nEnd1 = nEnd1 // 0x4
    if (nEnd1 == 0):
        break
    #print(hex(nEnd1))


print (sFlag)

随便泡泡

image-20231117190357449

ok了

image-20231117190417341