Frederick

Welcome to my Alter Ego's site!

Feb 24, 2025 - 8 minute read - Comments

nssctf逆向题

一些常见的逆向函数

index() find()找索引值

.append(ord()) +=chr()字母数字转换

简简单单的逻辑题

ord 字符串转ascii码
chr ascii码转字符串
hex 十进制转十六进制
int(a,16) 十六进制转十进制
[起点,终点,步长] python切片
zfill(2) 为不满2个宽度的字符串前添加0直到宽度为2

easy C

直接逆完事

\#include <stdio.h>

\#include <string.h>

int main()

{

  char b[] = "d`vxbQd";

  for (int i = 0; i < 7; i++)

  {

​    b[i] = b[i] ^ 2;

​    b[i]--;

  }

  printf("%s\n", b);

}

有点小难的逻辑题

flag = 'xxxxxxxxxxxxxxxxxxxxx'

s = 'wesyvbniazxchjko1973652048@$+-&*<>'

result = ''

for i in range(len(flag)):

  s1 = ord(flag[2*i])

  s2 = ord(flag[2*i+1])

  result += s[(s1+i)%34]+s[-(s2+i+1)%34]

print(result)

\# result = 'v0b9n1nkajz@j0c4jjo3oi1h1i937b395i5y5e0e$i'
#爆破脚本,菜狗不会逆向

result = 'v0b9n1nkajz@j0c4jjo3oi1h1i937b395i5y5e0e$i'

s = 'wesyvbniazxchjko1973652048@$+-&*<>'

flag = ''

l=range(len(result)//2)

#先找到s中的索引值

for i in l:

  indx1 = s.index(result[2*i])

  indx2 = s.index(result[2*i+1])

  for num in range(32,127):

​    s1 = num //17

​    s2 = num % 17

​    ds1 = (s1+i)%34

​    ds2 = -(s2+i+1)%34

​    if indx1 == ds1 and indx2 == ds2:

​      flag += chr(num)

​      break

print(flag)

思路:其实从s到result从分析学来看,就是一个数列重排,flag被用作一个对应的函数关系式,只要一一验证result和s的值在哪个地方相等,就可以求出flag,index()就是找result中的值在s的哪个位置,这个index再经过逆向/爆破,可以得到flag

fakerandom

random.seed():通过设置相同的随机种子,可以确保每次运行时获得相同的随机数序列

import random

flag = 'xxxxxxxxxxxxxxxxxxxx'

random.seed(1)

l = []

for i in range(4):

  l.append(random.getrandbits(8))

result=[]

for i in range(len(l)):

  random.seed(l[i])

  for n in range(5):

​    result.append(ord(flag[i*5+n])^random.getrandbits(8))

print(result)

\# result = [201, 8, 198, 68, 131, 152, 186, 136, 13, 130, 190, 112, 251, 93, 212, 1, 31, 214, 116, 244]


import random

result = [201, 8, 198, 68, 131, 152, 186, 136, 13, 130, 190, 112, 251, 93, 212, 1, 31, 214, 116, 244]

flag = []

random.seed(1)

l = []

for i in range(4):

  l.append(random.getrandbits(8))

print(l)

for i in range(len(l)):

  random.seed(l[i])

  for n in range(5):

​    flag.append((chr((result[i*5+n])^random.getrandbits(8))))

flag = ''.join(flag)

print(flag)

卡在签到题了…

if ( Str2[j] == 111 )
  Str2[j] = 48;

看到有个很像flag的{hello_world},提交结果发现错了,一看伪代码,发现把0改成了o,ASCII表o对应111,0对应48

花指令

  • jump

    start://花指令开始
        jmp label1
        DB junkcode
    label1:
         jmp label2
         DB junkcode
    label2:
        jmp label3
        DB junkcode
    label3   
    
  • jnz和jz跳转

_asm{
    jz label1
    jnz label1
    db junkcode
label1:    
}
  • 永真条件跳转
__asm{
    push ebx
    xor ebx,ebx
    test ebx,ebx
    jnz label1
    jz label2
label1:
    _emit junkcode
label2:
   pop ebx//需要恢复ebx寄存器    
}

__asm{
	clc
	jnz label1:
	_emit junkcode
label1:
}
  • call&ret构造花指令
__asm{
    call label1
    _emit junkcode
label1:
    add dword ptr ss:[esp],8//具体增加多少根据调试来
    ret
    _emit junkcode
}

call指令:将下一条指令地址压入栈,再跳转执行
ret指令:将保存的地址取出,跳转执行

例题

按D转换成数据形式

右键change bytes E8换成90 就是nop

后面变黄的地址c修复即可

转到函数开头p生成函数

[HUBUCTF 2022 新生赛]ezPython

拿到题目,发现文件时.pyz结尾,先转换成py格式

uncompyle 6 -o ezPython.py ezPython.pyz

from Crypto.Util.number import *
import base64, base58
password = open("password.txt", "r").read()
tmp = bytes_to_long(password.encode("utf-8"))
ans = base64.b64encode(base58.b58encode(str(tmp))).decode()
print("I've forgot my password,could you please help me find the password?")
if ans == "M0hBajFITHVLcWV6R1BOcEM5MTR0R0J3eGZVODV6MTJjZUhGZFNHQw==":
    print("You get the password!")
else:
    print("Wrong! try again")

解释下,bytes_to_long()把字节转换成长整型,加密成utf-8形式,再转为字符串,转为base58,转为base64,逆过来写就行

from Crypto.Util.number import *
import base64
import base58
import hashlib
flag1="M0hBajFITHVLcWV6R1BOcEM5MTR0R0J3eGZVODV6MTJjZUhGZFNHQw=="
flag= int(base58.b58decode(base64.b64decode(flag1)))
print(flag)

flag = long_to_bytes(flag)
flag.decode("utf-8")
flag = hashlib.md5(flag).hexdigest()
print(flag)

一些习惯:打开IDAshift f12查看字符串

ctrl+x 交叉引用

Z3-slover

Solver()

创建一个求解器,在里面添加约束条件进行下一步的求解

add()

通常在solver()命令之后,用来添加约束条件,通常添加的约束条件是一个等式

check()

判断是否添加的约束条件是否有解,有解返回sat,无解返回unsat

model()

在有解的情况下,求解的交集再输出创建求解约束器

solver = Solver

添加约束条件

solver.add()

判断解是否存在

 if solver.check()==sat

求解

print solver.model()

题目

#include <iostream>
using namespace std;

void flag_checker(int v, int w,int x,int y,int z); 

int main(){
	int v,w,x,y,z;
	cout << "Input 5 random number and check your luck ;)" << endl;
	cout << "Num1: ";
	cin >> v;
	cout << "Num2: ";
	cin >> w;
	cout << "Num3: ";
	cin >> x;
	cout << "Num4: ";
	cin >> y;
	cout << "Num5: ";
	cin >> z;
	cout << endl;
	flag_checker(v,w,x,y,z);
}


void flag_checker(int v,int w, int x, int y, int z){
	if ((v * 23 + w * -32 + x * 98 + y * 55 + z * 90 == 333322) &&
		(v * 123 + w * -322 + x * 68 + y * 67 + z * 32 == 707724) &&
		(v * 266 + w * -34 + x * 43 + y * 8 + z * 32 == 1272529) &&
		(v * 343 + w * -352 + x * 58 + y * 65 + z * 5 == 1672457) &&
		(v * 231 + w * -321 + x * 938 + y * 555 + z * 970 == 3372367)){
			cout << "Congratulations, Here is your flag:\n";
			cout << "flag{" << v << "_" << w << "_" << x << "_" << y << "_" << z << "}" << endl;
		}
		else{
			cout << "\nSeems your luck is not in favor right now!\nBetter luck next time!" << endl;
		}

}
from z3 import *
s=Solver()
v,w,x,y,z=Ints('v w x y z') #定义整数变量
s.add(v * 23 + w * -32 + x * 98 + y * 55 + z * 90 == 333322)
s.add(v * 123 + w * -322 + x * 68 + y * 67 + z * 32 == 707724)
s.add(v * 266 + w * -34 + x * 43 + y * 8 + z * 32 == 1272529)
s.add(v * 343 + w * -352 + x * 58 + y * 65 + z * 5 == 1672457)
s.add(v * 231 + w * -321 + x * 938 + y * 555 + z * 970 == 3372367)
s.check()
print(s.model())

[SWPUCTF 2022 新生赛]xor

image-20250225120439959

\#include <stdio.h>

\#include <stdlib.h>

\#include <string.h>

int main()

{

  char str[] = "LQQAVDyZMP]3q]emmf]uc{]vm]glap{rv]dnce";

  char flag[39];

  for (int i = 0; i <= 38; i++)

  {

​    flag[i] = str[i] ^ 2;

  }

  printf("%s", flag);

}

easyasm

cmp [ebp+i], eax

jge short loc_40119D (大于等于)

最主要是这两行,以及[ebp+i]一开始赋值为0

eax没有初始化,我想第一次循环是不会直接跳,所以继续执行后面的内容,看到xor eax, 33h,知道和55作异或运算,逆过来就是把明文每个作XOR运算

; void __cdecl enc(char *p)
.text:00401160 _enc            proc near               ; CODE XREF: _main+1B↑p
.text:00401160
.text:00401160 i               = dword ptr -4
.text:00401160 Str             = dword ptr  8
.text:00401160
.text:00401160                 push    ebb
.text:00401161                 mov     ebp, esp
.text:00401163                 push    ecx
.text:00401164                 mov     [ebp+i], 0
.text:0040116B                 jmp     short loc_401176
.text:0040116D ; ---------------------------------------------------------------------------
.text:0040116D
.text:0040116D loc_40116D:                             ; CODE XREF: _enc+3B↓j
.text:0040116D                 mov     eax, [ebp+i]
.text:00401170                 add     eax, 1
.text:00401173                 mov     [ebp+i], eax
.text:00401176
.text:00401176 loc_401176:                             ; CODE XREF: _enc+B↑j
.text:00401176                 mov     ecx, [ebp+Str]
.text:00401179                 push    ecx             ; Str
.text:0040117A                 call    _strlen
.text:0040117F                 add     esp, 4
.text:00401182                 cmp     [ebp+i], eax
.text:00401185                 jge     short loc_40119D
.text:00401187                 mov     edx, [ebp+Str]
.text:0040118A                 add     edx, [ebp+i]
.text:0040118D                 movsx   eax, byte ptr [edx]
.text:00401190                 xor     eax, 33h
.text:00401193                 mov     ecx, [ebp+Str]
.text:00401196                 add     ecx, [ebp+i]
.text:00401199                 mov     [ecx], al
.text:0040119B                 jmp     short loc_40116D
.text:0040119D ; ---------------------------------------------------------------------------
.text:0040119D
.text:0040119D loc_40119D:                             ; CODE XREF: _enc+25↑j
.text:0040119D                 mov     esp, ebp
.text:0040119F                 pop     ebp
.text:004011A0                 retn
.text:004011A0 _enc            endp
Input: your flag
Encrypted result: 0x5b,0x54,0x52,0x5e,0x56,0x48,0x44,0x56,0x5f,0x50,0x3,0x5e,0x56,0x6c,0x47,0x3,0x6c,0x41,0x56,0x6c,0x44,0x5c,0x41,0x2,0x57,0x12,0x4e
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char flag1[] = {0x5b, 0x54, 0x52, 0x5e, 0x56, 0x48, 0x44, 0x56, 0x5f, 0x50, 0x3, 0x5e, 0x56, 0x6c, 0x47, 0x3, 0x6c, 0x41, 0x56, 0x6c, 0x44, 0x5c, 0x41, 0x2, 0x57, 0x12, 0x4e};
    char flag[100] = {0};
    for (int i = 0; i < strlen(flag1); i++)
    {
        flag[i] = flag1[i] ^ 51;
    }
    printf("%s\n", flag);
}

你知道什么事python吗

s = str(input("please input your flag:"))


arr=[29, 0, 16, 23, 18, 61, 43, 41, 13, 28, 88, 94, 49, 110, 66, 44, 43, 28, 91, 108, 61, 7, 22, 7, 43, 51, 44, 46, 9, 18, 20, 6, 2, 24]

if(len(s)!=35  or s[0]!='N'):
    print("error")
    exit(0)

for i in range(1,len(s)):
    if(ord(s[i-1])^ord(s[i])!=arr[i-1]):
        print("error!")
        exit(0)
print("right!")
arr=[29, 0, 16, 23, 18, 61, 43, 41, 13, 28, 88, 94, 49, 110, 66, 44, 43, 28, 91, 108, 61, 7, 22, 7, 43, 51, 44, 46, 9, 18, 20, 6, 2, 24]
s = [''] * 35
s[0]='N'
for i in range(1,len(arr)+1):
    s[i]=chr(ord(s[i-1])^arr[i-1])
print("".join(s))

s=[’’]*35 分配初始空间

ord()转换成ascii码

chr()转换成字符

print("".join(s))拼接

安卓逆向

java -jar jadx-1.5.1-all.jar

文件拖进来

搜索字符串‘NO’

image-20250225192535250

text = '棿棢棢棲棥棷棊棐棁棚棨棨棵棢棌'

key = 987654321

flag = ''

for i in text:

  \# 将结果限制在有效的 Unicode 范围内,限制在0-255范围内

  flag += chr((ord(i) ^ key) % 256)

print(flag)

注意限制字符长度!

chicken_soup

花指令 E8改成90 p生成函数

%c直接转为ASCII码,c语言这点比python好

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    unsigned char a1[] = {0xCD, 0x4D, 0x8C, 0x7D, 0xAD, 0x1E, 0xBE, 0x4A, 0x8A, 0x7D,
                          0xBC, 0x7C, 0xFC, 0x2E, 0x2A, 0x79, 0x9D, 0x6A, 0x1A, 0xCC,
                          0x3D, 0x4A, 0xF8, 0x3C, 0x79, 0x69, 0x39, 0xD9, 0xDD, 0x9D,
                          0xA9, 0x69, 0x4C, 0x8C, 0xDD, 0x59, 0xE9, 0xD7};
    for (int i = 0; i < 38; i++)
    {
        a1[i] = (16 * a1[i]) | (a1[i] >> 4);
    }
    for (int j = 36; j > 0; j--)
    {
        a1[j] -= a1[j + 1];
    }
    for (int i = 0; i < 38; i++)
    {
        printf("%c", a1[i]);
    }
    return 0;
}

image-20250225212046924

image-20250225212059037

关了IDA忘记截图,索性拿别人wp

老鼠走迷宫

难崩,Windows环境有点难配

conda activate 2-27进入python3.6版本的conda环境,进入D盘目录pyinstxtractor

python pyinstxtractor.py 附件.exe

用struct.pyc修复5.pyc头文件

进入D盘pydcd的build

pycdc.exe 5.pyc

脚本

from collections import deque
 
#设置二维四向迷宫, 如果题目是多个小迷宫问题, 拆分多次调用脚本获取路径即可
(row, col) = (12, 12)
(i, j) = (0, 0)
maze =  [
 [
  1, 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, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
 [
  1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1],
 [
  1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1],
 [
  1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1],
 [
  1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
 [
  1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1],
 [
  1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1],
 [
  1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1],
 [
  1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1],
 [
  1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1],
 [
  1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
 [
  1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1],
 [
  1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1],
 [
  1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
 [
  1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1],
 [
  1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1],
 [
  1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
 [
  1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1],
 [
  1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1],
 [
  1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1],
 [
  1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
 [
  1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
 [
  1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 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, 0, 1]]
path_len = 0x7fffffff#如果题目未给出终点坐标,则一定会指定路径的长度,在此处修改路径长度,否则请保留path_len的极大值
 
#进行BFS寻找路径
def bfs(start, end, barrier):
    directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] # 定义四个方向的移动
    for i in range(len(maze)):#获取起点和终点在列表中的索引
        for j in range(len(maze[i])):
            if(maze[i][j] == start):
                start = (i, j)
            if(maze[i][j] == end):
                end = (i, j)
    #以下均是bfs算法套路
    queue = deque()
    queue.append((start, [start]))  # (当前位置, 路径)
    visited = set()
    visited.add(start)
    while queue:
        position, path = queue.popleft()
        if position == end:
            return path
        elif len(path)==path_len:
            return path
        for d in directions:
            next_position = (position[0] + d[0], position[1] + d[1])
            if 0 <= next_position[0] < len(maze) and 0 <= next_position[1] < len(maze[0]) and \
               maze[next_position[0]][next_position[1]] != barrier and next_position not in visited:
                queue.append((next_position, path + [next_position]))
                visited.add(next_position)
    return None
 
#执行BFS搜索并打印结果
if __name__ == '__main__':
    maze[0][1] = 'S' #如果题目给了起点终点的坐标,在这里直接给起点和终点添加特征
    maze[24][23] = 'E' 
    
    path = bfs('S', 'E', 1) #bfs函数传入参数代表起点、终点、障碍的特征(若题目给出的数据无特征, 手动添加特征即可, 通常障碍是1也有可能是0或其它字符如'#')
    print("移动路径坐标:", path)
    print("移动路径方位:{", end='')
    for i in range(1 ,len(path)):
        x1, y1, x2, y2 = path[i - 1][0], path[i - 1][1], path[i][0], path[i][1]
        if(x1 > x2):#上
            print("w", end='')
        elif(x1 < x2):#下
            print("s", end='')
        elif(y1 > y2):#左
            print("a", end='')
        elif(y1 < y2):#右
            print("d", end='')
    print('}')

随后md5加密

汇编语言 ctfshow-pwn

comments powered by Disqus