Reversing.kr 全解记录

前言

此篇文章记录了我对Reversing.kr网站的解题过程,有的直接看的wp,有的自己复现了一遍。
先开个头,后续会慢慢补充。

题解

0x0 Easy_CrackMe

Ea5yR3versing

0x1 Easy_KeygenMe

K3yg3nm3

0x2 Easy_UnpackMe

00401150

0x3 Music_Player

LIstenCare
这几题比较简单直接贴上答案

0x4 Replace

ida打开,定位到关键字符串,向上回溯,下断,跟了一遍,程序在0040466F mov byte ptr [eax], 90h处报错,结合逻辑分析,eax和我们的输入相关,0x90代表着nop,继续往下看调用堆栈。
Reversing.kr 全解记录_第1张图片
这里写图片描述
Reversing.kr 全解记录_第2张图片
最后要跳转到loc_401071,为了到达correct处,我们需要将loc_401071处的代码nop,通过程序自身代码就可以做到,我们只需使eax==0x401071即可。
答案:2687109798

0x5 ImagePrc

。。写着写着忘记保存了,东西都丢了。还是定位到关键函数,然后找到对比的资源文件,这里建议使用resourcehacker工具将资源文件dump下来,然后写个简单的脚本即可。

from PIL import Image

width = 200
height = 150

image_file = open('Data_1.bin', 'rb')
data = image_file.read()
image = Image.frombuffer('RGB', (width, height), data, 'raw', 'RGB')
image = image.transpose(Image.FLIP_TOP_BOTTOM)
image.show()
image_file.close()

答案:GOT

0x6 Easy ELF

很简单的不想写了
答案:L1NUX

0x7 ransomware

首先upx然后又是一堆花指令,写个简单的ipython脚本patch一下,这里还是需要手动的修改函数头55 8B EC 83 EC 24 53 56 57,然后使用ida重新f5一下便可以看到反编译后的结果。
Reversing.kr 全解记录_第3张图片
但是这个sub_401000函数还是被加了花,但是对逆向程序逻辑没有影响。
主要的加密过程,这里需要得到key值,观察pe文件可以看到题中给的hint,找到file文件对应的位置,解密得到key

enc='C7F2E2FFAFE3ECE9FBE5FBE1ACF0FBE5E2E0E7BEE4F9B7E8F9E2B3F3E5ACCBDCCDA6F1F8FEE9'.decode('hex')

dec='This program cannot be run in DOS mode'
key=''

enc = list(enc)
dec = list(dec)
for i in range(len(enc)):
    enc[i] = (~ord(enc[i]))&255
    key += chr(ord(dec[i])^enc[i])
print key

letsplaychess
最后解密file文件,得到exe文件,运行即可以得到flag

data_c = open('file','rb').read()
data_d=''
key='letsplaychess'
key_len = len(key)
for i in range(len(data_c)):
    data_d += chr(ord(key[i%key_len])^(~ord(data_c[i]))&255)

open('file.exe','wb').write(data_d)

答案:Colle System(我感觉如果没有提示有点脑洞了,看着wp写的)

0x8 CSHOP

这题有点神 输入一个空格 就可以看到 flag》??
不过还是有必要了解这个文件格式的CSHOP.exe: PE32 executable (GUI) Intel 80386 Mono/.Net assembly, for MS Windows
./net框架,采用c#编写,使用dnSpy进行反编译,然后可以修改IL指令。感觉这个dnSpy工具还是用的少。
答案:P4W6RP6SES

0x9 Direct3D_FPS

我的电脑上无法运行这个程序,只能静态分析了,ida分析字符串,交叉引用到byte_407028
Reversing.kr 全解记录_第4张图片
其中byte_407028的数据十分的可疑,但是无法确定result为何值,向上回溯,可以发现sub_403400在一个循环体中,可以猜测resulto-len(byte_407028),但是另一个角度来说,resultv2*4是线性关系,所以影响不大。
但是问题来了,通过交叉引用byte_409184发现此数据只有读的引用,没有写,因此在程序初始化时,此数据将被初始化,那么之前说了,我无法运行此程序,因此我在程序init下断,查看此时的byte_409184数据,我这里显示的都为0,但是我看wp却说是存在byte_409184[528*i] = 4*i这样的关系。
23333.

flag_c='436B666B62756C694C455C455F5A461C07252529701734390116494C20150B0FF7EBFAE8B0FDEBBCF4CCDA9FF5F0E8CEF0A9'.decode('hex')
flag_d=''
for i in range(len(flag_c)):
    flag_d += chr(ord(flag_c[i])^4*i)
print flag_d
#Congratulation~ Game Clear! Password is Thr3EDPr0m

0x10 HateIntel

mac下的程序,但是我没有mac的电脑,pizza来说静态看就是了,不过程序也简单,通过字符串,定位到关键函数(我经常这么写,因为确实是这么做的!)
Reversing.kr 全解记录_第5张图片
算法不可逆,但是可以逐字节爆破,脚本也简单,注意下uint_8变量范围0-256即可。

dic = [0x44, 0xF6, 0xF5, 0x57, 0xF5, 0xC6, 0x96, 0xB6, 0x56, 0xF5, 0x14, 0x25, 0xD4, 0xF5, 0x96, 0xE6, 0x37, 0x47, 0x27, 0x57, 0x36, 0x47, 0x96, 0x03, 0xE6, 0xF3, 0xA3, 0x92, 0x00]
flg = ''
for j in range(len(dic)):
    for fl in range(256):
        k = fl
        for i in range(4):
            tmp = (k*2)
            if tmp&0x100:
                tmp |= 1
            k = tmp%256
        if k == dic[j]:
            flg +=chr(fl)
print flg

答案:Do_u_like_ARM_instructi0n?:)

0x11 Flash Encrypt

下载ffdec工具同样的分析字符串,依次输入1456,25,44,8,88,20546
这题我没有复现,flash打不开。
答案:16876

0x12 Position

这题之前做z3总结的时候做过,写出约束条件,然后z3求解即可

from z3 import *
username = [BitVec('u%d'%i,8) for i in range(0,4)]
solver = Solver() #76876-77776
solver.add(((username[0]&1)+5+(((username[1]>>2) & 1 )+1))==ord('7')-0x30)
solver.add(((((username[0]>>3) & 1)+5)+(((username[1]>>3)&1)+1))==ord('6')-0x30)
solver.add((((username[0]>>1) & 1)+5+(((username[1]>>4) & 1 )+1))==ord('8')-0x30)
solver.add((((username[0]>>2) & 1)+5+(((username[1]) & 1 )+1))==ord('7')-0x30)
solver.add((((username[0]>>4) & 1)+5+(((username[1]>>1) & 1 )+1))==ord('6')-0x30)
solver.add((((username[2]) & 1)+5+(((username[3]>>2) & 1 )+1))==ord('7')-0x30)
solver.add((((username[2]>>3) & 1)+5+(((username[3]>>3) & 1 )+1))==ord('7')-0x30)
solver.add((((username[2]>>1) & 1)+5+(((username[3]>>4) & 1 )+1))==ord('7')-0x30)
solver.add((((username[2]>>2) & 1)+5+(((username[3]) & 1 )+1))==ord('7')-0x30)
solver.add((((username[2]>>4) & 1)+5+(((username[3]>>1) & 1 )+1))==ord('6')-0x30)
solver.add(username[3] == ord('p'))
for i in range(0,4):
    solver.add(username[i] >= ord('a'))
    solver.add(username[i] <= ord('z'))

solver.check()
result = solver.model()

flag = ''
for i in range(0,4):
    flag += chr(result[username[i]].as_long().real)
print flag

以上全部参考 https://veritas501.space/2017/03/04/Reversing.kr%20writeup/

0x13 SimpleVm

加壳并且需要逆vm
ida动态调试,然后dump出内存

static main(void)
{
    auto fp,dex_addr,end_addr;
    fp=fopen("/home/jeb/Downloads/Reverse.Kr/SimpleVM/dump.dex","wb");
    end_addr=0x804C000;
    for(dex_addr=0x8048000;dex_addr

脱完壳之后,分析起来还是十分的困难,因为没有函数的导入表,我们需要手动的去识别!
我们可以静态和动态结合起来去看。
对于脱完壳之后的这几个函数。
Reversing.kr 全解记录_第6张图片
我们可以通过动态的去寻找相应的函数,例如我们在源程序中搜索804B020导入表所对应的函数
Reversing.kr 全解记录_第7张图片
进而定位到libc
Reversing.kr 全解记录_第8张图片
f5可以看到最后有个vfork,所以猜测该函数为libcfork函数。
Reversing.kr 全解记录_第9张图片
类似的我们可以慢慢的定位其他函数。
大概如下
父进程:
Reversing.kr 全解记录_第10张图片
子进程:
Reversing.kr 全解记录_第11张图片
由于程序中对wrong correct等字符串进行了加密,所以无法直接搜索得到,但同样可以利用动静结合的方式,得出。
Reversing.kr 全解记录_第12张图片
Reversing.kr 全解记录_第13张图片
为了使其输出正确,我们需要使func==1 && dword_804B190!=0,但是func函数确实太繁琐了。
Reversing.kr 全解记录_第14张图片
这个函数存在一个xor操作
Reversing.kr 全解记录_第15张图片
这里有一个判断操作,所以我们可以尝试侧信道攻击。
是时候拿出我们的利器pintools
但是我在使用pinCTF工具进行长度爆破时,程序直接卡死了,而且直接确定好长度后也同样会报错,本来我以为这个github项目的容错性比较好,最后试了一下还是自己写脚本比较靠谱。
先是手动尝试flag的长度
Reversing.kr 全解记录_第16张图片
比较清楚的看到flag长度为7,这里需要注意一点的是由于改程序存在子进程,所以会有两个Count,这也是为什么pinCTF工具出错的原因!
手动的测试了第一个字符为i
Reversing.kr 全解记录_第17张图片
从结果来看,主要抓住第二个Count即可
最终脚本如下:

shell = shell()
dic = string.letters+'_+*/'+string.digits
cout_old = 234174
cur=''
for i in range(7):
    for s in dic:
        shell.initPin(cmd)
        pwd = cur+s+'?'*(6-len(cur))
        print pwd
        shell.pinWrite(pwd+'\n')
        sout,serr = shell.pinRun()
        cout = sout.split("Count ")[2]
        cout_sub= int(cout) - cout_old
        cout_old = int(cout)
        if cout_sub > 10 and cout_sub < 1000:
            cur=cur+s
            break
        print ("current cur ", cur,"current count:",cout,"sub_count ",cout_sub)

Reversing.kr 全解记录_第18张图片
有关pintools的使用可以参考我之前写的几篇文章。
答案;id3*ndh
参考文章:
https://blog.csdn.net/whklhhhh/article/details/78221365
http://www.freebuf.com/news/164664.html
第二篇文章的思路也很好,做vm的题就是需要耐心,而且很多时候我们是没有办法去动态调试的,需要硬着头皮静态分析。

0x14 AutoHotkey1

这题很蒙,看了wp还是没有复现出来,upx脱壳之后就不知道干什么了,目标不是很明确!
最后是解两个md5
答案:isolated pawn
第二天又看了一遍,还是没做出来,感觉OD用的不熟

0x15 AutoHotkey2

感觉这题比1要友好,至少不用对着一堆壳代码进行分析。根据字符串定位到关键函数。这是一个程序自校验的函数。
Reversing.kr 全解记录_第19张图片
sub_4508C7返回0
程序逻辑我是动态调试分析的。
Reversing.kr 全解记录_第20张图片
Reversing.kr 全解记录_第21张图片
v11是相对固定的,所以我们需要手动的修改最后四个字节,以使程序不会崩溃
结果是A15A7F44,继续往下。
Reversing.kr 全解记录_第22张图片
这里需要注意理解fseek(*v3, (int)v3[1], 0);
此时的文件指针指向的是0x90839adc也就是程序后8个字节所指向的地址。
这里写图片描述
然后取出改地址中的16个字节同,固定字节进行比较。因此我们需要在程序中找到对应数据所在的位置。
Reversing.kr 全解记录_第23张图片
所以我们修改倒数8个字节为006e0600,通过手动修改标志位寄存器可以得到
Reversing.kr 全解记录_第24张图片
英文翻译一下,得到答案:jonsnow
其实做到最后发现这题不修改程序也是可以的,只要在动态调试遇见跳转时手动修改ZF值即可,最终也能走到最后的分支,也能弹出那段提示!

0x16 CRC1

算法好难!如果是crc32那就很简单的,但是64感觉增加了一个维度。
程序的逻辑很简单,就是输入一个8位的flag,然后替换一个内置的table,之后使用crc64进行加密,最后的结果与某个值进行比较。
实在是太笨了,看了wp还是没有复现出来。
答案:CrCA1g@!

0x17 CRC2

这题更加看不懂了。
贴下答案:goodRevKrF0rU

参考链接
这位国外的老哥太强了!

0x18 CustomShell

这题我现在只能给个参考链接
需要在本地搭建AVR调试环境。

0x19 CSharp

这题还是比较有意思的,了解了./net程序的破解以及IL指令
首先dySpn反编译,从程序逻辑可以看出有一个方法被加密了,在运行时会进行解密,但是我们无法动态的跟进去,有两种方法。

第一种:

得到解密后的IL code,使用ILByteDecoder工具解密得到IL指令,整体来说IL指令并不复杂

IL_0000: ldarg.1 
IL_0001: ldlen 
IL_0002: conv.i4 
IL_0003: ldc.i4.s 0xC
IL_0005: bne.un 
IL_000A: ldarg.0 
IL_000B: ldc.i4.0 
IL_000C: ldc.i4.2 
IL_000D: stelem.i1 
IL_000E: ldarg.1 
IL_000F: ldc.i4.0 
IL_0010: ldelem.u1 
IL_0011: ldc.i4 0x10
IL_0016: xor 
IL_0017: ldc.i4.s 0x4A
IL_0019: beq.s 
IL_001B: ldarg.0 
IL_001C: ldc.i4.0 
IL_001D: ldc.i4.1 
IL_001E: stelem.i1 
IL_001F: ldarg.1 
IL_0020: ldc.i4.3 
IL_0021: ldelem.u1 
IL_0022: ldc.i4 0x33
IL_0027: xor 
IL_0028: ldc.i4.s 0x46
IL_002A: beq.s 
IL_002C: ldarg.0 
IL_002D: ldc.i4.0 
IL_002E: ldc.i4.1 
IL_002F: stelem.i1 
IL_0030: ldarg.1 
IL_0031: ldc.i4.1 
IL_0032: ldelem.u1 
IL_0033: ldc.i4 0x11
IL_0038: xor 
IL_0039: ldc.i4.s 0x57
IL_003B: beq.s 
IL_003D: ldarg.0 
IL_003E: ldc.i4.0 
IL_003F: ldc.i4.1 
IL_0040: stelem.i1 
IL_0041: ldarg.1 
IL_0042: ldc.i4.2 
IL_0043: ldelem.u1 
IL_0044: ldc.i4 0x21
IL_0049: xor 
IL_004A: ldc.i4.s 0x4D
IL_004C: beq.s 
IL_004E: ldarg.0 
IL_004F: ldc.i4.0 
IL_0050: ldc.i4.1 
IL_0051: stelem.i1 
IL_0052: ldarg.1 
IL_0053: ldc.i4.s 0xB
IL_0055: ldelem.u1 
IL_0056: ldc.i4 0x11
IL_005B: xor 
IL_005C: ldc.i4.s 0x2C
IL_005E: beq.s 
IL_0060: ldarg.0 
IL_0061: ldc.i4.0 
IL_0062: ldc.i4.1 
IL_0063: stelem.i1 
IL_0064: ldarg.1 
IL_0065: ldc.i4.8 
IL_0066: ldelem.u1 
IL_0067: ldc.i4 0x90
IL_006C: xor 
IL_006D: ldc.i4 0xF1
IL_0072: beq.s 
IL_0074: ldarg.0 
IL_0075: ldc.i4.0 
IL_0076: ldc.i4.1 
IL_0077: stelem.i1 
IL_0078: ldarg.1 
IL_0079: ldc.i4.4 
IL_007A: ldelem.u1 
IL_007B: ldc.i4 0x44
IL_0080: xor 
IL_0081: ldc.i4.s 0x1D
IL_0083: beq.s 
IL_0085: ldarg.0 
IL_0086: ldc.i4.0 
IL_0087: ldc.i4.1 
IL_0088: stelem.i1 
IL_0089: ldarg.1 
IL_008A: ldc.i4.5 
IL_008B: ldelem.u1 
IL_008C: ldc.i4 0x66
IL_0091: xor 
IL_0092: ldc.i4.s 0x31
IL_0094: beq.s 
IL_0096: ldarg.0 
IL_0097: ldc.i4.0 
IL_0098: ldc.i4.1 
IL_0099: stelem.i1 
IL_009A: ldarg.1 
IL_009B: ldc.i4.s 0x9
IL_009D: ldelem.u1 
IL_009E: ldc.i4 0xB5
IL_00A3: xor 
IL_00A4: ldc.i4 0xE2
IL_00A9: beq.s 
IL_00AB: ldarg.0 
IL_00AC: ldc.i4.0 
IL_00AD: ldc.i4.1 
IL_00AE: stelem.i1 
IL_00AF: ldarg.1 
IL_00B0: ldc.i4.7 
IL_00B1: ldelem.u1 
IL_00B2: ldc.i4 0xA0
IL_00B7: xor 
IL_00B8: ldc.i4 0xEE
IL_00BD: beq.s 
IL_00BF: ldarg.0 
IL_00C0: ldc.i4.0 
IL_00C1: ldc.i4.1 
IL_00C2: stelem.i1 
IL_00C3: ldarg.1 
IL_00C4: ldc.i4.s 0xA
IL_00C6: ldelem.u1 
IL_00C7: ldc.i4 0xEE
IL_00CC: xor 
IL_00CD: ldc.i4 0xA3
IL_00D2: beq.s 
IL_00D4: ldarg.0 
IL_00D5: ldc.i4.0 
IL_00D6: ldc.i4.1 
IL_00D7: stelem.i1 
IL_00D8: ldarg.1 
IL_00D9: ldc.i4.6 
IL_00DA: ldelem.u1 
IL_00DB: ldc.i4 0x33
IL_00E0: xor 
IL_00E1: ldc.i4.s 0x75
IL_00E3: beq.s 
IL_00E5: ldarg.0 
IL_00E6: ldc.i4.0 
IL_00E7: ldc.i4.1 
IL_00E8: stelem.i1 
IL_00E9: ret 

IL指令集的参考文章
整体来说,先判断长度ldc.i4.s 0xC bne.un ,然后异或之后判断,不过这样子还是比较的麻烦的。

第二种:

得到解密后的hex我们可以选择覆盖源程序,然后重新使用dySpn反编译,这样就不需要自己去分析IL指令了。
经过一番折腾之后终于得到了解密后的程序。
Reversing.kr 全解记录_第25张图片
所以加密的过程很简单,难点在于如何解密该函数。
我大致说一下过程。
首先如下两个断点
Reversing.kr 全解记录_第26张图片
调试,查看此时的Form1.bb值,据此在文件中找到相应的位置。
Reversing.kr 全解记录_第27张图片

运行到解密处,然后将此时的Form.bbdump出来。
Reversing.kr 全解记录_第28张图片
覆盖文件中的对应位置的值,保存.exe然后重新使用dnSpy加载,此时就可以看到反编译后的结果了。
解密脚本如下:(直接用的夜影师傅的代码)

import base64
bt = [0 for i in range(12)]

bt[0] = 16 ^ 74
bt[3] = 51 ^ 70
bt[1] = 17 ^ 87
bt[2] = 33 ^ 77
bt[11] = 17 ^ 44
bt[8] = 144 ^ 241
bt[4] = 68 ^ 29
bt[5] = 102 ^ 49
bt[9] = 181 ^ 226
bt[7] = 160 ^ 238
bt[10] = 238 ^ 163
bt[6] = 51 ^ 117

flag = ''
for i in bt:
    flag+=(chr(i))

print(base64.b64decode(flag))

参考文章
答案:`dYnaaMic

0x20 JavaCrackMe

一道简单的java题,我的ubuntu不知道咋滴jd-gui死活无法运行,最后下载了jadx,然后反编译。
Reversing.kr 全解记录_第29张图片
就这么几行代码。
知识点就是一个long类型溢出,有符号数的运算。
Reversing.kr 全解记录_第30张图片
所以-1536092243306511225L很明显是溢出了,
该值在内存应为2**64-(-1536092243306511225L)=0xeaaeb43e477b8487L
然后简单运算一下,无法整除。
这里写图片描述
那么便可以说明,高位全部溢出了,所以我们需要爆破出高位。
在编写代码时暂且不考虑有无符号

i = 1

while(1):
    k = i*2**64  + 0xEAAEB43E477B8487
    if(k % 26729 == 0):
        print k
        print(k/26729)
        print(2**64-k/26729)
        break
    else:
        i += 1

k=0x3597eaaeb43e477b8487L爆破出高位为3597
所以答案为8978084842198767761

0x21 LOTTO

这题表示不太明白出题人的意图??
输入仅仅是用来同伪随机函数进行判断,并没有用于flag的加密,所以直接设置ipflag输出的位置即可。
这里写图片描述
参考了夜影师傅的文章,发现还有很多解题的思路。
一种方法,由于是伪随机,那么我们便可以写一个程序,然后传入参数给lotto程序。
如下代码:

#include 
#include 
#include 
void main()
{
    char s[100];
    int n[6], i;
    time_t t;
    t = _time64(NULL);#得到当前时间秒数
    srand(t);#随机数生成种子
    for(i=0;i<6;i++)
        n[i] = rand()%100;#取出数列中的6个数
    sprintf(s, "echo %d %d %d %d %d %d | F:\\ctf\\reversing.kr\\Lotto\\Lotto.exe", n[0], n[1], n[2], n[3], n[4], n[5]);#生成通过管道送入值的字符串
    system(s);#控制台调用
    system("pause");
}

第二种,直接用python复现一遍算法。不贴代码了。

0x22 MetroApp

很抱歉这题,由于
提示说Windows8 MetroStyle App,环境我懒得搭建了,所以就直接静态的看了。
IDA搜索字符串没发现什么结果,但是我手动看了下rdata段,还是发现了一些可疑字符,从而可以定位到关键函数。
Reversing.kr 全解记录_第31张图片
好多windows api不认识,上msdn搜一下即可
WindowsCompareStringOrdinal比较字符串是否相等
WindowsCreateStringReference创建新的字符串引用
那么很明显
sub_40F4E0便是用来获取用户输入的。
![这里写图片描述](https://img-blog.csdn.net/2018090209013962?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzNDM4NzMz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
除了
v1 = ((int (__stdcall *)(int, int ))((_DWORD *)a1 + 24))(a1, &v7);// 类似于 jni的作用不了解外,其它都可以知道,难道答案就是MERONG???这也太简单了吧!很明显不是的。
在一头雾水之时,我仔细的分析了
correct分支,发现运行到这里时并没有return`而是跳转到了另一个大循环中。
Reversing.kr 全解记录_第32张图片
Reversing.kr 全解记录_第33张图片
上面一大段代码没怎么看懂,直到。。

v50 = WindowsGetStringRawBuffer(v41, 0);
v51 = WindowsGetStringRawBuffer(v45, 0);
v52 = WindowsGetStringRawBuffer(v49, 0);

通过交叉引用我发现这三个变量均来自固定的结构。
Reversing.kr 全解记录_第34张图片
因此我猜测v3 = (*(int (__stdcall **)(int, int *))(*(_DWORD *)v38 + 24))(v38, &v98);便是用于获取用户输入的具体函数,当然这仅仅是猜测
Reversing.kr 全解记录_第35张图片
那么这一段便是加密验证的部分,继续往下查看,发下v80类似i用于自增
最后我们需要直到比较的对象是谁,对v50查交叉引用,最后我找到了v100,但是好像没什么用处。

LOBYTE(v1) = *(_WORD *)(v50 + 2 * v80 + 2) != (unsigned __int8)(byte_4307A8[v80 & 7] ^ __ROL1__(
                                                                                               *(_BYTE *)(v52 + 2 * v80),
                                                                                               *(_WORD *)(v51 + 2 * v80) & 7));

我继续关注了这个验证的代码。
__ROL1__函数第一个参数是变量,第二个参数是右移的长度,所以正常来说,v51应该是长度信息才对,v52是字符信息,我又仔细看了三者的来源,发现v51和v52的来源相同,v50则不同,所以又可以猜测,这应该是某种结构体,存放了长度和字符信息,类似与a[n+1]==a[n]>>len(a[n]&7)^(4307a8[n&7])
好,现在理清楚了,程序会从第一个字符开始,生成一串字符串,根据某种线性关系进行验证。这时可以想起来提示的意图了。Password must be composed of uppercase letter and digit
这里可能稍微需要补充下ROL指令,循环左移。
所以我们编写脚本,遍历大写和数字字符,根据条件爆破出符合条件的字符串。

def ROR(x, n,bits = 8):
    mask = (2L**n) - 1
    mask_bits = x & mask
    return (x >> n) | (mask_bits << (bits - n))

def ROL(x, n ,bits = 8):
    return ROR(x, bits - n,bits)
byte_4307a8 = [0x77,0xAD,0x07,0x02,0xA5,0x00,0x29,0x99]
flag = []
s = [0]
for i in range(48,90):
    s[0]= i
    for j in range(20):
        k = byte_4307a8[j&7]^ROL(s[j],s[j]&7,bits = 8)
        if (not k):
            flag.append(s)
            break
        s.append(k)
    s=[0]
r = ''
for i in flag:
    for j in i:
        r+=chr(j)
    print r
    r=''

最后得到两组解,所以最后的答案:D34DF4C3
这个蛮难的,感觉全是靠感觉猜的。233333

0x23 PEPassword

总结

现在还没到总结的时候!

你可能感兴趣的:(Re)