easyre

2024-10-30T08:44:11.png

reverse1

reverse2

内涵的软件

新年快乐

xor

reverse3

helloword

不一样的flag

SimpleRev

[GXYCTF2019]luck_guy

Java逆向解密

[BJDCTF2020]JustRE

刮开有奖

[ACTF新生赛2020]easyre

简单注册器

[GWCTF 2019]pyre

findit

[ACTF新生赛2020]rome

RSA

完全不会,从头记录一下

目录结构如下:

RSA
├─flag.enc
└pub.key

解析一下公钥

-----BEGIN PUBLIC KEY-----
MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhAMAzLFxkrkcYL2wch21CM2kQVFpY9+7+
/AvKr1rzQczdAgMBAAE=
-----END PUBLIC KEY-----
key长度256
模数C0332C5C64AE47182F6C1C876D42336910545A58F7EEFEFC0BCAAF5AF341CCDD
指数65537 (0x10001)

所以
n=86934482296048119190666062003494800588905656017203025617216654058378322103517
e=65535
然后把n放到factordb解一下,得到
p=285960468890451637935629440372639283459
q=304008741604601924494328155975272418463
运行以下脚本,得到flag

import rsa
import gmpy2

n = 86934482296048119190666062003494800588905656017203025617216654058378322103517
e = 65537
p = 285960468890451637935629440372639283459
q = 304008741604601924494328155975272418463
D = int(gmpy2.invert(e, (p - 1) * (q - 1)))
private_key = rsa.PrivateKey(n, e, D, p, q)
with open('flag.enc', 'rb+') as f:
    flag = f.read()
    f.close()
flag = rsa.decrypt(flag, private_key)
print(flag)

[FlareOn4]login

<!DOCTYPE Html />
<html>
    <head>
        <title>FLARE On 2017</title>
    </head>
    <body>
        <input type="text" name="flag" id="flag" value="Enter the flag" />
        <input type="button" id="prompt" value="Click to check the flag" />
        <script type="text/javascript">
            document.getElementById("prompt").onclick = function () {
                var flag = document.getElementById("flag").value;
                var rotFlag = flag.replace(/[a-zA-Z]/g, function(c){return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);});
                if ("PyvragFvqrYbtvafNerRnfl@syner-ba.pbz" == rotFlag) {
                    alert("Correct flag!");
                } else {
                    alert("Incorrect flag, rot again");
                }
            }
        </script>
    </body>
</html>

一眼rot13

import codecs

def rot13(text):
    return codecs.encode(text, 'rot_13')

text = "PyvragFvqrYbtvafNerRnfl@syner-ba.pbz"
encoded_text = rot13(text)
print(encoded_text)

[WUSTCTF2020]level1

level1反编译结果

with open("output.txt", "r") as f:
    data = f.read().split("\n")
    print(data)
    f.close()

for i in range(1, 20):
    if (i & 1) == 0:
        print(chr(int(data[i - 1]) // i), end="")
    else:
        print(chr(int(data[i - 1]) >> i), end="")

[GUET-CTF2019]re

用upx去壳后,发现有很多函数,使用字符串搜索找到实际的主函数

GUETCTF2019re主函数

发现是sub_4009AE决定结果,进去看

GUETCTF2019resub4009AE

发现全是这种比较,所以拼接出结果:

注意if的顺序15-17处有坑,另外缺少6,暴力得出是1。所以代码中的if为6时加1不是一开始的脚本,时最后方便观察结果添加的

conditions = [
    (1629056, 166163712),
    (6771600, 731332800),
    (3682944, 357245568),
    (10431000, 1074393000),
    (3977328, 489211344),
    (5138336, 518971936),
    (7532250, 406741500),
    (5551632, 294236496),
    (3409728, 177305856),
    (13013670, 650683500),
    (6088797, 298351053),
    (7884663, 386348487),
    (8944053, 438258597),
    (5198490, 249527520),
    (4544518, 445362764),
    (10115280, 981182160),
    (3645600, 174988800),
    (9667504, 493042704),
    (5364450, 257493600),
    (13464540, 767478780),
    (5488432, 312840624),
    (14479500, 1404511500),
    (6451830, 316139670),
    (6252576, 619005024),
    (7763364, 372641472),
    (7327320, 373693320),
    (8741520, 498266640),
    (8871876, 452465676),
    (4086720, 208422720),
    (9374400, 515592000),
    (5759124, 719890500)
]

a1_values = []
for index, (multiplier, result) in enumerate(conditions):
    if index == 6:
        a1_values.append(ord("1"))
    a1_value = result // multiplier
    a1_values.append(a1_value)
    print(f"a1[{index}] = {chr(a1_value)}")

print("".join(map(chr, a1_values)))

CrackRTF

进IDA后分析主函数逻辑:

CrackRTFpart1

可以看到,第一组密码需要输入一个长度为⑥的数,然后与@DBApp拼接后,进入sub_40100A函数后,与6E32D0943418C2C33385BC35A1470250DD8923A9比较,正确后进去下一部分

分析sub_40100A函数:

CrackRTFpart2

关注到函数CryptCreateHash,这是一个win32api

CryptCreateHash 函数启动数据流的哈希处理。 它将创建 加密服务提供程序 的句柄,并将其返回给调用应用程序, (CSP) 哈希对象。 此句柄用于后续调用 CryptHashData 和 CryptHashSessionKey ,以便对会话密钥和其他数据流进行哈希处理。

其用法如下:

BOOL CryptCreateHash(
  [in]  HCRYPTPROV hProv,
  [in]  ALG_ID     Algid,
  [in]  HCRYPTKEY  hKey,
  [in]  DWORD      dwFlags,
  [out] HCRYPTHASH *phHash
);

关注到第二个参数[in] Algid,该参数决定了计算的类型,查阅类型表可知,0x8004u代表计算sha1

于是使用python脚本去碰撞,找到第一个password

import hashlib

string = "@DBApp"

for i in range(100000, 1000000):
    if hashlib.sha1((str(i) + string).encode("UTF8")).hexdigest() == "6E32D0943418C2C33385BC35A1470250DD8923A9".lower():
        print(f"Password1: {i}")
        password1 = i
        break

# password1 = 123321

继续分析第二部分

CrackRTFpart4

CrackRTFpart5

查表可得0x8003u是MD5

如果运气好,可以在MD5库里找到答案~!3a@0123321@DBApp

CrackRTFpart6

如果你没有找到,还是可以继续做(因为发现答案正确,会提示Error,而且用密码去提交不是flag),直接研究sub_40100F函数

CrackRTFpart7

发现sub_401005还有对这个值的校验

CrackRTFpart7

看起来是个异或的操作,那应该可是可以还原出来而不是去md5库里找

回到sub_40100F,发现给sub_401005的值都来自于Resource中,所以使用Resource Hacker读取一下AAA的内容

ResourceHacker

因为我们已知第二部分也是6位,所以取前6个[0x05, 0x7d, 0x41, 0x15, 0x26, 0x01]

然后已知异或的另一部分是dbapp.rtf的头,所以异或的另一部分是{\rtf1

import hashlib

string = "@DBApp"

for i in range(100000, 1000000):
    if hashlib.sha1((str(i) + string).encode("UTF8")).hexdigest() == "6E32D0943418C2C33385BC35A1470250DD8923A9".lower():
        print(f"Password1: {i}")
        break

# password1 = 123321


part1 = [0x05, 0x7d, 0x41, 0x15, 0x26, 0x01]
part2 = r"{\rtf1"

for i in range(6):
    part1[i] ^= ord(part2[i])

print("Password2:", end=" ")
print("".join([chr(i) for i in part1]))

#password2 = ~!3a@0

最后从输出的文件dbapp.rtf里找到flag

[WUSTCTF2020]level2

UPX之后嗯,直接看到
WUSTCTF2020-level2

[2019红帽杯]easyRE

进IDA,发现诡异的类似base64的值
easyRE

非正常解法(x


然后解10次base64(PS:为什么是10次呢?因为每次解完后还是像base64,直到第10次x)

easyRE2

在评论区找到答案

easyRE3

找到主函数

easyRE4

[MRCTF2020]Transform

进IDA看到逻辑清晰的主函数

Transform1

分析主函数可知,flag长为33,按照qword_40F040中数值的顺序与之异或后比较

Transformqword40f040

Transformword40f0e0

Transformexp

[SUCTF2019]SignIn

进IDA反编译

SignIn

观察到几个重点sub_96A、一个65537__gmpz_powm

这几个构成很像RSA,查询GNU MP库相关函数mpz_init_set_strmpz_powm 应该是RSA没跑了

解一下大数,得到p和q,然后使用脚本得到flag

SignInpq

SignInRSA

[ACTF新生赛2020]usualCrypt

分析主函数

2024-10-30T03:55:54.png

发现比较的部分是word_40E0E4,把这一块提取出来,然后重点关注函数sub_401080

2024-10-30T03:58:12.png

看起来像是base64,但是直接解不对,所以猜测可能是base64_table被修改

2024-10-30T04:07:56.png

果然在sub_401000里发现了蹊跷,还原后还是不对,继续看,发现最后还有一个sub_401030,分析后得出是大小写转换,最后脚本得出flag

2024-10-30T04:21:38.png

[HDCTF2019]Maze

初见,不会,进IDA,没法分析,百度,需要手动patch然后再分析,记录一下过程

2024-10-30T08:18:42.png

这里jnz产生跳转,但是下面的跳转指令到了0ec85d78dh这样一个不存在的地址,中断了IDA的自动分析。这种指令成为花指令,因此我们需要把他patch掉,然后让IDA能够自动分析。

2024-10-30T08:23:09.png
2024-10-30T08:23:25.png

IDA就恢复正常了,保存patch,然后重新用IDA打开就可以正常的分析了

2024-10-30T08:24:56.png
2024-10-30T08:27:19.png

初始是7和0,走了13步后变成5和-4,但是这样就会有很多flag的可能,所以继续查看,最后找到maze地图

2024-10-30T08:28:31.png

*******+**
******* **
****    **
**   *****
** **F****
**    ****
**********
# flag{ssaaasaassdddw}

[MRCTF2020]Xor

进IDA,发现无法使用F5查看反编译结果,不过看流程不复杂,直接分析

MRCTF2020Xor

前三块的主要内容是读取一个以零结尾的字符串,计算其长度,并检查长度是否为 27

loc_4010B6:
mov     al, [edx]
inc     edx
test    al, al
jnz     short loc_4010B6
sub     edx, ecx
cmp     edx, 1Bh                      ; 比较 edx 和 27 (1Bh) 的值
jnz     short loc_4010FF              ; 如果 edx 不等于 27,跳转到 loc_4010FF,表示字符串长度不符合预期
xor     eax, eax                      ; 将 eax 清零(后面比较会用到)
db      66h, 66h
nop     word ptr [eax+eax+00000000h]

然后是左侧的几块,用来异或并且与data区0x41ea08内容比较

loc_4010D0:
mov     cl, byte_4212C0[eax]              ; 从 byte_4212C0 加上 eax 偏移量的位置读取一个字节到 cl
xor     cl, al                            ; 将 cl 与 al 进行异或操作,结果存回 cl
cmp     cl, ds:byte_41EA08[eax]           ; 将 cl 与 byte_41EA08 加上 eax 偏移量的位置的字节进行比较
jnz     short loc_4010FF                  ; 如果比较结果不相等,跳转到 loc_4010FF,表示验证失败
inc     eax                               ; 增加 eax 的值,指向下一个字节
cmp     eax, edx                          ; 比较 eax 和 edx,检查是否遍历完所有字节
jb      short loc_4010D0
push    offset aRight   ; "Right!\n"
call    sub_401020
push    offset aPause   ; "pause"
call    sub_404B7E
add     esp, 8
xor     eax, eax
retn

因此,从0x41ea08拿到数据,然后异或还原即可得到flag

# Python>[idc.get_wide_byte(0x41ea08+i) for i in range(27)]
byte_41EA08 = [0x4d, 0x53, 0x41, 0x57, 0x42, 0x7e, 0x46, 0x58, 0x5a, 0x3a, 0x4a, 0x3a, 0x60, 0x74, 0x51, 0x4a, 0x22, 0x4e, 0x40, 0x20, 0x62, 0x70, 0x64, 0x64, 0x7d, 0x38, 0x67]
for i in range(27):
    print(chr(byte_41EA08[i] ^ i), end="")

[MRCTF2020]hello_world_go

额?可能2020年还没IDA pro 8不能这么方便的反汇编?反正直接出结果

2024-10-30T08:11:22.png

最后修改:2024 年 10 月 30 日
如果觉得我的文章对你有用,请随意赞赏