NSSCTF_RE(二)暑期

[CISCN 2021初赛]babybc

在这里插入图片描述
LLVM是那个控制流平坦化混淆,bc是IR指令文件
在这里插入图片描述
在这里插入图片描述
得到64位elf文件
然后就慢慢分析,感觉太妙了我靠
一个数独游戏,用二个二维数组添加约束,一个二维数组作地图,慢慢看
最后用 z3 来解数独,也是 vary nice
在这里插入图片描述

from z3 import *

from hashlib import md5

# 限制条件

rowss = [[0x00, 0x00, 0x00, 0x01],

         [0x01, 0x00, 0x00, 0x00],

         [0x02, 0x00, 0x00, 0x01],

         [0x00, 0x00, 0x00, 0x00],

         [0x01, 0x00, 0x01, 0x00]]

# 限制条件

colnms = [[0x00, 0x00, 0x02, 0x00, 0x02],

          [0x00, 0x00, 0x00, 0x00, 0x00],

          [0x00, 0x00, 0x00, 0x01, 0x00],

          [0x00, 0x01, 0x00, 0x00, 0x01]]

s = Solver()

# 初始化题目

map = [[None] * 5,

       [None] * 5,

       [None] * 5,

       [None] * 5,

       [None] * 5]

for i in range(5):

    for j in range(5):
        map[i][j] = Int("x%d%d" % (i, j))  # 先初始化设置未知数

s.add(map[2][2] == 4)

s.add(map[3][3] == 3)  # 添加条件: 有两个位置已知

# 设置限制条件

for i in range(5):

    for j in range(5):
        s.add(map[i][j] >= 1)

        s.add(map[i][j] <= 5)  # 添加条件: 填的数字为1-5

for i in range(5):

    for j in range(5):

        for k in range(j):
            s.add(map[i][j] != map[i][k])  # 添加条件: 一行中不能有相同

for j in range(5):

    for i in range(5):

        for k in range(i):
            s.add(map[i][j] != map[k][j])  # 添加条件: 一列中不能有相同

for i in range(5):

    for j in range(4):

        if rowss[i][j] == 1:

            s.add(map[i][j] > map[i][j + 1])

        elif rowss[i][j] == 2:

            s.add(map[i][j] < map[i][j + 1])  # 根据题目分析添加条件

for i in range(4):

    for j in range(5):

        if colnms[i][j] == 2:

            s.add(map[i][j] > map[i + 1][j])

        elif colnms[i][j] == 1:

            s.add(map[i][j] < map[i + 1][j])  # 根据题目分析添加条件

answer = s.check()

if answer == sat:

    print(s.model())

    m = s.model()

    flag = []

    for i in map:

        for j in i:
            flag.append(m[j].as_long())

    print(flag)

    for i in range(len(flag)):
        flag[i] += 48

    flag[12] = 48

    flag[18] = 48

    flag = bytes(flag)

    print("CISCN{%s}" % md5(flag).hexdigest())

# Flag=CISCN{8a04b4597ad08b83211d3adfa1f61431}

[HNCTF 2022 WEEK4]ez_maze

uncompyle6不能反编译pyc
pycdc打开,就是一个简单的31*31的maze,不过需要注意的是只能走0
学着写了一个 DFS 解密脚本

from hashlib import md5
map1 = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1],
        [1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1],
        [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
        [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
        [1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1],
        [1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1],
        [1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1],
        [1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1],
        [1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1],
        [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
        [1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1],
        [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1],
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1],
        [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1],
        [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
        [1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1],
        [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
        [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
        [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
        [1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
        [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1],
        [1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1],
        [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1],
        [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1],
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
        ]
# record go track
map2=[[0 for _ in range(len(map1))] for _ in range(len(map1))]
flag=""

def DFS(row,col):
    global flag
    go=0
    if row==29 and col==29: # finally
        print(flag)
        res=flag
        return res
    # first check next row whether can go and be noticed
    if map1[row+1][col]==go and map2[row+1][col]==0:
        # if can,go and notice and 递归
        map2[row][col]=1
        flag+='s'
        DFS(row+1,col)
        # 回溯操作
        flag=flag[:-1]
        map2[row][col]=0
    if map1[row-1][col]==go and map2[row-1][col]==0:
        map2[row][col]=1
        flag+='w'
        DFS(row-1,col)
        flag=flag[:-1]
        map2[row][col]=0
    if map1[row][col-1]==go and map2[row][col-1]==0:
        map2[row][col]=1
        flag+='a'
        DFS(row,col-1)
        flag=flag[:-1]
        map2[row][col]=0
    if map1[row][col+1]==go and map2[row][col+1]==0:
        map2[row][col]=1
        flag+='d'
        DFS(row,col+1)
        flag=flag[:-1]
        map2[row][col]=0

if __name__ == '__main__':
    start_row=1
    start_col=1
    DFS(start_row,start_col)
    enc='ssssddssaassddddwwwwddwwddddddwwddddddssddwwddddddddssssaawwaassaassaassddssaassaawwwwwwaaaaaaaassaassddddwwddssddssssaassddssssaaaaaawwddwwaawwwwaassssssssssssddddssddssddddddddwwaaaaaawwwwddssddwwwwwwwwddssddssssssssddddss'
    enc=enc.encode()
    print(md5(enc).hexdigest())

[GDOUCTF 2023]L!s!

在这里插入图片描述
两个 64位的elf文件
一个应该是 patch 了
两个程序的main好像差不多都是一千多行代码,前面有很多case语句
结合文件的名字,这两个文件可能只有一点细微的差异,其他内容都是一样的

识别二进制文件中的差异,可以使用 IDA 的 BinDiff 插件
工具下的有点问题,烦 jdk 0.0
算了,反正来学一下解密
厨子的使用
感觉自己很多都不会用啊,学学
在这里插入图片描述
在这里插入图片描述
记一下:

def little_endian(num, width_num):  # 将小端序转换为正序  
    global buffer  
    hex_str = hex(num)  # 将int数据转换为十六进制的字符串  
    while len(hex_str) != width_num + 2:  
        hex_str = "0x" + "0" * (width_num - len(hex_str[2:])) + hex_str[2:]  # 位数不足width的用0凑齐  
    index = width_num  
    while index >= 2:  
        tmp = int((hex_str[index: index + 2]), 16)  # 每两位string转换为十六进制int型数据  
        buffer.append(tmp)  # 将int型作为char存入buffer  
        index -= 2  
    return buffer  
  
  
buffer = []  # 存放结果的列表  
  
lmao1 = 0x7D2E370A180F1604  
lmao2 = 0x3F7D132A2A252822  
lmao3 = 0x392A7F3F39132D13  
lmao4 = 0x31207C7C381320  
  
little_endian(lmao1, 16)  
little_endian(lmao2, 16)  
little_endian(lmao3, 16)  
little_endian(lmao4, 14)  
  
print(buffer)  
# [4, 22, 15, 24, 10, 55, 46, 125, 34, 40, 37, 42, 42, 19, 125, 63, 19, 45, 19, 57, 63, 127, 42, 57, 32, 19, 56, 124, 124, 32, 49]  
  
for key in range(256):  # 直接爆破key  
    flag = ""  
    print("key = ", key)  
    for k in range(len(buffer)):  
        tmp = buffer[k] ^ key  # 逐个与key异或  
        flag += chr(tmp)  # 对应的字符存入flag  
    print(flag)  
    if 'HZCTF' in flag or 'NSSCTF' in flag:  # 只输出包含'HZCTF'或'NSSCTF'的结果  
        break

注意学习了那个端序的处理
也还有一种,不过不太好记

import struct  
  
stack_bytes = [  
    0x7d2e370a180f1604,  
    0x3f7d132a2a252822,  
    0x392a7f3f39132d13,  
    0x31207c7c381320  
]  
  
# 将stack_bytes中的数据按照小端字节序打包为二进制数据  
xored_bytes = struct.pack("<4Q", *stack_bytes)  
# 其中,< 表示小端序,Q代表一个无符号长整型  
# 每个无符号长整型整数占8个字节,所以总共打包出来的字符串长度为32个字节  
# b'\x04\x16\x0f\x18\n7.}"(%**\x13}?\x13-\x139?\x7f*9 \x138|| 1\x00'  
  
for xorkey in range(256):  
    output = bytes(byte ^ xorkey for byte in xored_bytes)  
    if b"HZCTF{" in output:  
        print(output)  
  
# b'HZCTF{b1ndiff_1s_a_us3ful_t00l}L'  
# (因为在lmao4的高位补了一个0,所以多输出了一个L)

Art

在这里插入图片描述
在这里插入图片描述
angr 跑了半天没出来
只能爆破了
在这里插入图片描述

flag=[0]*27+[125]
enc=[2,  24,  15, 248,  25,   4,  39, 216, 235,   0,
   53,  72,  77,  42,  69, 107,  89,  46,  67,   1,
   24,  92,9, 9, 9, 9, 181, 125]
# for i in range(1,len(enc),1):
#     Str1[i - 1] ^= (Str1[i - 1] % 17 + Str1[i]) ^ 25
#     str[i-1]=sre[i-1]^25^(str[i-1]%17+str[i])
#     str[26]=str[26]^25^(str[26]%17+str[27])
def dfs(index):
    if index ==0:
        for j in flag:
            print(chr(j),end='')
        print()
    else:
        for i in range(32,128,1):
            if (i^25)^(i%17+flag[index])==enc[index-1]:
                flag[index-1]=i
                dfs(index-1)
dfs(27)
# (i^25)^(i%17+flag[27])==enc[26]

对于逆向来说,算法还是很重要的

不可大意

在这里插入图片描述
要注意顺序

z3使用

from z3 import *
s=Solver()
charArray=[BitVec(f"charArray[{i}]",8) for i in range(9)]
s.add((charArray[0] * 4778) + (charArray[1] * 3659) + (charArray[2] * 9011) + (charArray[3] * 5734) + (charArray[4] * 4076) + (charArray[5] * 6812) + (charArray[6] * 8341) + (charArray[7] * 6765) + (charArray[8] * 7435) == 5711942)
s.add((charArray[0] * 4449) + (charArray[1] * 5454) + (charArray[2] * 4459) + (charArray[3] * 5800) + (charArray[4] * 6685) + (charArray[5] * 6120) + (charArray[6] * 7357) + (charArray[7] * 3561) + (charArray[8] * 5199) == 4885863 )
s.add((charArray[0] * 3188) + (charArray[1] * 6278) + (charArray[2] * 9411) + (charArray[3] * 5760) + (charArray[4] * 9909) + (charArray[5] * 7618) + (charArray[6] * 7184) + (charArray[7] * 4791) + (charArray[8] * 8686) == 6387690)
s.add( (charArray[0] * 8827) + (charArray[1] * 7419) + (charArray[2] * 7033) + (charArray[3] * 9306) + (charArray[4] * 7300) + (charArray[5] * 5774) + (charArray[6] * 6588) + (charArray[7] * 5541) + (charArray[8] * 4628) == 6077067)
s.add( (charArray[0] * 5707) + (charArray[1] * 5793) + (charArray[2] * 4589) + (charArray[3] * 6679) + (charArray[4] * 3972) + (charArray[5] * 5876) + (charArray[6] * 6668) + (charArray[7] * 5951) + (charArray[8] * 9569) == 5492294)
s.add((charArray[0] * 9685) + (charArray[1] * 7370) + (charArray[2] * 4648) + (charArray[3] * 7230) + (charArray[4] * 9614) + (charArray[5] * 9979) + (charArray[6] * 8309) + (charArray[7] * 9631) + (charArray[8] * 9272) == 7562511)
s.add( (charArray[0] * 6955) + (charArray[1] * 8567) + (charArray[2] * 7949) + (charArray[3] * 8699) + (charArray[4] * 3284) + (charArray[5] * 6647) + (charArray[6] * 3175) + (charArray[7] * 8506) + (charArray[8] * 6552) == 5970432)
s.add( (charArray[0] * 4323) + (charArray[1] * 4706) + (charArray[2] * 8081) + (charArray[3] * 7900) + (charArray[4] * 4862) + (charArray[5] * 9544) + (charArray[6] * 5211) + (charArray[7] * 7443) + (charArray[8] * 5676) == 5834523)
s.add((charArray[0] * 3022) + (charArray[1] * 8999) + (charArray[2] * 5058) + (charArray[3] * 4529) + (charArray[4] * 3940) + (charArray[5] * 4279) + (charArray[6] * 4606) + (charArray[7] * 3428) + (charArray[8] * 8889) == 4681110)

if s.check()==sat:
    m=s.model()
    print(m)
    print(len(m))
    data=[]
    for i in range(9):
        data.append((m[charArray[i]].as_long()))
    for i in range(9):
        print(chr(data[i]),end='')

TEA_Apk

在这里插入图片描述
还有一个 base64

最外面函数
在这里插入图片描述
在这里插入图片描述

看的太头疼了

中间函数
在这里插入图片描述
也是大致清楚了,就是将 byte 转 int

barr.length & 3 (11) == 0

相当于 / 4 ,算出 int 的长度
然后根据 z 来 new int 数组空间,如果 true ,长度加一,最后元素为原计算长度
,false 就是原长度

( bArr[i] & 255) << ( ( i & 3) << 3 ) | iArr[i2]

byte - int 关键, &255 确保在 0-255 之间, ( ( i & 3) << 3 ) 算偏移

>>> 无符号右移

里面
在这里插入图片描述
这个应该只是检查长度是否是16
wp 看了一下,原来一整个是 XXTEA 加密,工具直接可以解,不过还是分析了一下,确实很难逆
翻半天,就只有一个大佬的脚本

import base64
from ctypes import c_uint32

import libnum

DELTA = 0x9E3779B9


def decrypt(v, n, k):
    rounds = 6 + int(52 / n)
    sum = c_uint32(rounds * DELTA)
    y = v[0].value
    while rounds > 0:
        e = (sum.value >> 2) & 3
        p = n - 1
        while p > 0:
            z = v[p - 1].value
            v[p].value -= (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum.value ^ y) + (k[(p & 3) ^ e] ^ z)))
            y = v[p].value
            p -= 1
        z = v[n - 1].value
        v[0].value -= (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum.value ^ y) + (k[(p & 3) ^ e] ^ z)))
        y = v[0].value
        sum.value -= DELTA
        rounds -= 1


enc = "vlgg9nNjUcYuWzBSSOwKxbMD2rhFgf4zuiyMpLxpNkM="
key = "ABvWW7hqwNvHUhfP"
enc = base64.b64decode(enc.encode())
print(enc)
e = list(map(lambda i: c_uint32(int(enc[i:i + len(enc) // 8][::-1].hex(), 16)), range(0, len(enc), len(enc) // 8)))
print(e)
k = list(map(lambda i: int(key[i:i + len(key) // 4].encode()[::-1].hex(), 16), range(0, len(key), len(key) // 4)))
print(k)
decrypt(e, len(e), k)
print(b''.join(map(lambda x: libnum.n2s(x.value)[::-1], e)))


研究一下

[长城杯 2021 院校组]Just_cmp-re

估计是 hook strcmp 了吧
在这里插入图片描述
运行到 call 报错了
在这里插入图片描述
翻到了这个函数
额,就很逆向

data=[  0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x07, 0x0A, 0x37, 0x0A,
  0x08, 0x0A, 0x06, 0x06, 0x0B, 0x38, 0x07, 0x0A, 0x3B, 0x08,
  0x38, 0x0E, 0x0F, 0x3B, 0x3A, 0x0A, 0x0B, 0x06, 0x09, 0x07,
  0x3B, 0x37, 0x0D, 0x0F, 0x07, 0x38, 0x0F, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
enc='flag{********************************}'
flag=''
for i in range(len(enc)):
    flag+=chr(ord(enc[i])+data[i])
print(flag)

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值