Buuoj reverse

  • helloworld
  • reverse3
  • 不一样的flag
  • SimpleRev
  • Java逆向解密
  • [GXYCTF2019]luck_guy


好久没刷题了,我太忙了,后边争取每天刷

helloworld

该文件为apk,使用jadx-gui打开

java Flowable 详细教程 java flag_v9

flag{7631a988259a00816deda84afb29430a}

reverse3

32位pe文件

java Flowable 详细教程 java flag_字符串_02


顺序分析,输入flag保存在str种,经过sub_4110BE函数获得Destination,并经过一个循环简单处理后,与str2比较。

先查看str2

java Flowable 详细教程 java flag_v9_03


别忘了这个变换

java Flowable 详细教程 java flag_python_04

再查看sub_4110BE

java Flowable 详细教程 java flag_v9_05


java Flowable 详细教程 java flag_v9_06

一般这种形式是base64编码,编写一个脚本解决了

import base64

st = 'e3nifIH9b_C@n@dH'
my = ''
for i,item in enumerate(st):
    my += chr(ord(st[i])-i)

print((base64.b64decode(my)).decode())

flag{i_l0ve_you}

不一样的flag

32位pe

java Flowable 详细教程 java flag_java Flowable 详细教程_07

对主函数进行分析,首先注意v3是一个字符串,并且根据输出字符串判断需要选择上下左右的行为,接下来的逻辑便是分别对v3[25]和v4进行赋值,其中v3的前25个字符都是确定的,v3[25]可以看作不为字符串的一个变量。

down时,v3[25]加一,up时减一。right时,v4加一,left时v4减一。并且对v3[25]和v3[29](为v4)进行0~4范围确定,之后根据5*v3[25]+v4来确定是否为’1’(49)或者’#'(35),可知v3为一个迷宫,如下:

'*1111' 
'01000' 
'01010' 
'00010' 
'1111#'

从’*‘(0,0)开始到’#'为止,因此flag为

flag{222441144222}

SimpleRev

64位elf文件

java Flowable 详细教程 java flag_python_08

发现存在Decry()函数

java Flowable 详细教程 java flag_网络安全_09


这个函数很有意思,分为两部分分析,首先是其对字符串key和text的定义(后续主要用到)。text是由key3和v9拼接得到,key3很好得到为‘kills’,v9则是存储的十六进制大端序,而在arm使用时用的是小端序,因此需要将v9转换为字符串并且反向,因此text和key分别为:

key = 'adsfkndcls'
test = 'killshadow'

得到两个字符串的定义之后,继续分析之后的逻辑

java Flowable 详细教程 java flag_python_10


简单分析其主要逻辑是,输入flag字符串,如果在65~90之间、0~64或者122~255之间都可以根据key的值对str2赋值,为简单获得flag,我选择如下脚本

key = 'adsfkndcls'
test = 'killshadow'

flag = ''
k=0
for i in test:
    for j in range(65,91,1):
        if ord(i) == (j-39-ord(key[k])+97)%26+97:
            flag+=chr(j)
    k+=1
print(flag)

flag{KLDQCUDFZO}

Java逆向解密

看到java直接上jadx

java Flowable 详细教程 java flag_java Flowable 详细教程_11


简单的静态分析,照着keylist逆一下就行,我把大括号直接复制到python,以为它是中括号,搞了半天不对,甚至调试了一下才发现括号搞错了。唉,java菜鸡。

st = [180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65]

flag = ''
for i in st:
    flag += chr((i^32)-ord('@'))

print(flag)
flag{This_is_the_flag_!}

[GXYCTF2019]luck_guy

好名字,希望我后半生能是个luck guy

java Flowable 详细教程 java flag_字符串_12


选择一个幸运数字,我选好了,然后进入他的patch_me函数

java Flowable 详细教程 java flag_网络安全_13


没错,我选的就是偶数,然后进入他的get_flag函数

java Flowable 详细教程 java flag_java Flowable 详细教程_14

主要逻辑还是一个只有5次机会的循环,而且每次选择都是随机数,还要mod200,可以,也就是1/200的概率选择一个分支,然后,还需要先选4再选5,最后选1,算下来最快的成功率是1/8000000,不错不错。打比赛的时候可以直接循环运行这个程序,迟早出结果,也可以找个幸运人直接试,一把就出。

但是我命由我不由天,flag由f1和f2拼接成的,f1直接得出,f2则通过字节存储后(和之前一样需要注意小端序转换),经过一点点变化得到,脚本如下

st = '\x7Ffo`guci'
st = st[::-1]
f1 = 'flag{do_not_'
f2 = ''
for i,item in enumerate(st):
    if i % 2 == 1:
        f2+=chr(ord(item) - 2)
    else:
        f2+=chr(ord(item) - 1)

print(f1 + f2)
flag{do_not_hate_me}