
查看代码,里面有一堆加法,然后传入了init中的方法int()、exit()、exec、m()方法
先对python代码进行简单的简化
查看一下init.pyd中的方法
pyd_info.py:
import init
x = dir(init)
print("fun b: " ,init.b)
print("fun c: " , init.c)
print("fun e: " , init.e)
print("fun exec: " , init.exec)
print("fun exit: " , init.exit)
print("fun int: " , init.int)
print("fun m: " , init.m)
print("fun p: " , init.p)
help(init)
#result:
'''
fun b: <function b64encode at 0x0000000001671F70>
fun c: <class 'unicorn.unicorn_py3.unicorn.Uc'>
fun e: <unicorn.unicorn_py3.arch.intel.UcIntel object at 0x0000000001522F10>
fun exec: <cyfunction exec at 0x000000000147F5F0>
fun exit: <built-in function eval>
fun int: <class 'str'>
fun m: <class 'operator.methodcaller'>
fun p: <built-in function print>
Help on module init:
NAME
init
FUNCTIONS
a2b_hex(hexstr, /)
Binary data of hexadecimal representation.
hexstr must contain an even number of hex digits (upper or lower case).
This function is also available as "unhexlify()".
exec(x)
exit = eval(source, globals=None, locals=None, /)
Evaluate the given source in the context of globals and locals.
The source may be a string representing a Python expression
or a code object as returned by compile().
The globals must be a dictionary and locals can be any mapping,
defaulting to the current globals and locals.
If only globals is given, locals defaults to it.
i = input(prompt=None, /)
Read a string from standard input. The trailing newline is stripped.
The prompt string, if given, is printed to standard output without a
trailing newline before reading input.
If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.
On *nix systems, readline is used if available.
p = print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.
DATA
__test__ = {}
e = <unicorn.unicorn_py3.arch.intel.UcIntel object>
FILE
c:\users\36134\desktop\2025羊城杯\re\re2\chal\init.pyd
*/
'''从help中可以看出
b = b64encode()
p = print(...)
i = input(prompt=None, /)
exit = eval()
e = <unicorn.unicorn_py3.arch.intel.UcIntel object>
m = operator.methodcaller()
init.int()函数是str类型了,尝试调用这个函数

这个函数实现了加法,返回str类型的和
init.exec()函数暂时看不出来,先放着,根据从init.pyc中得知的信息,将脚本简化
处理脚本:
import re
with open("plus.py", "r") as f:
data = f.read()
matches = re.findall(r'int\((.*?)\)', data)
solve = []
for i in matches:
if i == '':
solve.append('')
else:
solve.append(eval(i))
for i, match in enumerate(matches):
data = data.replace(f'int({match})', f"'{solve[i]}'")
solve2 = []
matches = re.findall(r'exit\((.*?)\)', data)
for i in matches:
solve2.append(eval(i))
for i, match in enumerate(matches):
data = data.replace(f'exit({match})', f"{solve2[i]}")
data = data.replace(';','\n')
print(data)
处理之后代码:
from init import *
m(exec(30792292888306032),16777216,2097152)(e)
m(exec(30792292888306032),18874368,65536)(e)
m(exec(2018003706771258569829),16777216,exec(2154308209104587365050518702243508477825638429417674506632669006169365944097218288620502508770072595029515733547630393909115142517795439449349606840082096284733042186109675198923974401239556369486310477745337218358380860128987662749468317325542233718690074933730651941880380559453),)(e)
m(exec(2110235738289946063973),44,18939903)(e)
m(exec(2018003706771258569829),18878464, i(exec(520485229507545392928716380743873332979750615584)).encode())(e)
m(exec(2110235738289946063973),39,18878464)(e)
m(exec(2110235738289946063973),43,44)(e)
m(exec(2110235738289946063973),40,7)(e)
m(exec(1871008466716552426100), 16777216, 16777332)(e)
p(exec(1735356260)) if (b(m(exec(7882826979490488676), 18878464, 44)(e)).decode()== exec(636496797464929889819018589958474261894226380884858896837050849823120096559828809884712107801783610237788137002972622711849132377866432975817021)) else p(exec(31084432670685473)) #type:ignoree();m();init.exec查看处理之后的代码,有一个很大的int数值传入了init.exec(),调用这个函数查看

这个函数实现了int2str的功能
自己实现方法:
def int2bytes(n, byteorder: str = "big"):
if n == 0:
return b"\x00"
length = (n.bit_length() + 7) // 8
return n.to_bytes(length, byteorder)接下来分析m() e()方法
m()方法是operator.methodcaller(),这个方法用来创建函数,类似于回调函数
m(x1, x2, x3)(e)等价于e.x1(x2,x3)
e()方法是unicorn.unicorn_py3.arch.intel.UcIntel
Unicorn 是一个基于 QEMU 的CPU 模拟器框架
可以将上面e写成e = unicorn.Uc(UC_ARCH_X86, UC_MODE_64),第一个参数是cpu架构,第二个参数是模式
根据上面的分析,就可以将plus.py还原成原本的代码
from unicorn import *
from unicorn.x86_const import *
from operator import methodcaller
from base64 import b64encode as b
e = Uc(UC_ARCH_X86, UC_MODE_64)
e.mem_map(16777216,2097152)
e.mem_map(18874368,65536)
#写入汇编指令
e.mem_write(16777216,b'\xf3\x0f\x1e\xfaUH\x89\xe5H\x89}\xe8\x89u\xe4\x89\xd0\x88E\xe0\xc7E\xfc\x00\x00\x00\x00\xebL\x8bU\xfcH\x8bE\xe8H\x01\xd0\x0f\xb6\x00\x8d\x0c\xc5\x00\x00\x00\x00\x8bU\xfcH\x8bE\xe8H\x01\xd0\x0f\xb6\x002E\xe0\x8d4\x01\x8bU\xfcH\x8bE\xe8H\x01\xd0\x0f\xb6\x00\xc1\xe0\x05\x89\xc1\x8bU\xfcH\x8bE\xe8H\x01\xd0\x8d\x14\x0e\x88\x10\x83E\xfc\x01\x8bE\xfc;E\xe4r\xac\x90\x90]')
e.reg_write(44,18939903)
e.mem_write(18878464,input("[+]input your flag: ").encode())
e.reg_write(39,18878464)
e.reg_write(43,44)
e.reg_write(40,7)
e.emu_start(16777216,16777332)
print("good") if (
b(e.mem_read(18878464,44)).decode()
== "425MvHMxtLqZ3ty3RZkw3mwwulNRjkswbpkDMK+3CDCOtbe6kzAqPyrcEAI="
) else print("no way!")
e = Uc(UC_ARCH_X86, UC_MODE_64)e.mem_map(16777216,2097152)0x01000000(十进制 16777216)映射 2MB 内存,作为放置并执行 shellcode 的区域e.mem_map(18874368,65536)0x01200000(十进制 18874368)映射 64KB 内存,作为数据区e.mem_write(16777216, b'\xf3\x0f\x1e\xfa...')0x01000000e.reg_write(44,18939903)18939903 。代码里并没有以名字注明是哪个寄存器,但其作用是给 shellcode 一个初始化值e.mem_write(18878464,input("[+]input your flag: ").encode())
把用户的输入写到地址 18878464 这个地址和上面 data 区的基址有关系:
18878464 - 18874368 = 4096 = 0x1000所以输入被写入 data 区内偏移 0x1000 的位置(也就是 0x01201000)
三个 reg_write:
e.reg_write(39,18878464)
e.reg_write(43,44)
e.reg_write(40,7)这三行把函数参数或工作寄存器设为:
18878464)44)7)e.emu_start(16777216,16777332)0x01000000 执行,直到 0x01000000 + 116,执行过程中,shellcode 会读取/写入 data 区最后比较:
b(e.mem_read(18878464,44)).decode() == "425MvHMxtLqZ3ty3RZkw3mwwulNRjkswbpkDMK+3CDCOtbe6kzAqPyrcEAI="先对处理后的 44 字节用 base64编码得到字符串,再和enc进行比较

将汇编指令以二进制保存,使用ida打开分析,稍微处理一下数据类型和变量名

这里使用异或和乘法进行运算,因为除法不能直接逆运算,所以要爆破
写脚本爆破flag
import base64
enc = base64.b64decode("425MvHMxtLqZ3ty3RZkw3mwwulNRjkswbpkDMK+3CDCOtbe6kzAqPyrcEAI=")
flag = ''
for i in range(44):
for j in range(32,127):
if ((8 * j) + (7 ^ j) + (32 * j)) &0xff == enc[i]:
flag += chr(j)
break
print(flag)
#result
#DASCTF{un1c0rn_1s_u4fal_And_h0w_ab0ut_exec?}
]]>64位elf

ida分析

分析这几个函数
init函数初始化了一个table,一看就是rc4加密

继续看crypt1 和 crypt2, 是魔改的rc4

before_main函数加密key,秘钥是keykey

after_main函数使用加密之后的key作为秘钥加密了flag

def crypt1(s,key, key_len):
v5 = 0
v6 = 0
res = []
for i in range(key_len):
v5 = (v5 + 1) % 256
v6 = (v6 + s[v5]) % 256
v4 = s[v5]
s[v5] = s[v6]
s[v6] = v4
res.append(key[i] ^ (s[(s[v5] + s[v6]) %256]))
return res
def crypt2(s,enc,enc_len):
v5 = 0
v6 = 0
res = []
for i in range(enc_len):
v5 = (v5 + 1) % 256
v6 = (v6 + s[v5]) % 256
v4 = s[v5]
s[v5] = s[v6]
s[v6] = v4
res.append(enc[i] + s[(s[v5] + s[v6])%256])
return res
def init(s,key,key_len):
v8 = [0]*258
for i in range(256):
s[i] = i
v8[i] = key[i % key_len]
v6 =0
for j in range(256):
v6 = (v8[j] + v6 + s[j]) % 256
v4 = s[j]
s[j] = s[v6]
s[v6] = v4
s = [0]*256
key1 = [ord(b) for b in "keykey"]
key = [ord(b) for b in "ban_debug!"]
init(s,key1,len(key1))
res = crypt1(s,key,len(key))
print(res)
s2 = [0]*256
key2 = init(s2, res,len(res))
enc = [0x4E, 0x47, 0x38, 0x47, 0x62, 0x0A, 0x79, 0x6A, 0x03, 0x66,
0xC0, 0x69, 0x8D, 0x1C, 0x84, 0x0F, 0x54, 0x4A, 0x3B, 0x08,
0xE3, 0x30, 0x4F, 0xB9, 0x6C, 0xAB, 0x36, 0x24, 0x52, 0x81,
0xCF]
flag = crypt2(s2,enc,len(enc))
for i in flag:
print(chr(i%256),end="")
'''
运行结果
[105, 13, 90, 178, 64, 234, 25, 63, 47, 106]
flag{1237-12938-9372-1923-4u92}
'''
有upx, 十六进制查看upx特征是否被修改

将这三个ABC改回成UPX就能脱壳

ida分析代码
main函数中看到一个密文

往下看 很明显的base64加密,查看a9876543210zyxw数组

是base64换表

赛博厨子直接一把梭

拿到题目先查壳

是windows 64为的程序
双击打开,随便输如测试

根据题目名字,推测这是使用mfc框架开发的
直接上ida
在import中搜索messagebox跟到调用这个函数的地方
发现了验证flag的地方
v7中存的是加密的flag ^0x87 就能还原flag

直接上脚本
encode = [0xE0E6EBE1, 0x0E3E1B6FC, 0x0BEB7B6B2,
0x0B2B1BEE2, 0x0E2B6B6B2, 0x0B3B0B3E2,
0x0E3E3B2E2,0x0B7B7B3E2,0x0B6B0E6B0,0x0FAE1
]
for i in encode:
tmp = i.to_bytes(4,'little')
for j in tmp:
print(chr(j^0x87), end="")flag{1fd5109e965511ee474e5dde4007a71f}]]>
提示是xxtea加密

用ida打开,找到了key和加密后的data值

跟进去encode函数查看 发现这并不是xxtea加密,而是xtea加密,比赛的时候一直在用xxtea的脚本解,没解出来

接下来提取key和encode_data
将qword_400E80和qword_400E88拆成4个dword数据就是key即
int key[] = {0xDEADBEEF,87654321,0xFACEB00C,0xCAFEBABE};将encode_data也按照上述的数据类型提取
int data[] = {0x168F8672,0x2DBD824,0x0CF647FCA,0x0E6EFA7EF,0x4AE016F0,0x0C5832E1D,0x455C0A05,0x0FFEB8140,0x0BE9561EF,0x7F819E23,0x3BC04269,0x0C68B825B,0x0E6A5B1F0,0x0BD03CBBD,0x0A9B3CE0E,0x6C85E6E7,0x9F5C71EF,0x3BE4BD57};
直接拿脚本解密
#include <stdio.h>
#include <stdint.h>
/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */
void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
for (i=0; i < num_rounds; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
}
v[0]=v0; v[1]=v1;
}
void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
for (i=0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0]=v0; v[1]=v1;
}
int main()
{
uint32_t encode_data[]={
0x168F8672,0x2DBD824,0x0CF647FCA,0x0E6EFA7EF,0x4AE016F0,0x0C5832E1D,0x455C0A05,
0x0FFEB8140,0x0BE9561EF,0x7F819E23,0x3BC04269,0x0C68B825B,0x0E6A5B1F0,0x0BD03CBBD,
0x0A9B3CE0E,0x6C85E6E7,0x9F5C71EF,0x3BE4BD57
};
uint32_t const key[] = {0xDEADBEEF,0x87654321,0xFACEB00C,0xCAFEBABE};
unsigned int r=32;//num_rounds建议取值为32
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
// printf("加密前原始数据:%u %u\n",v[0],v[1]);
// encipher(r, v, k);
// printf("加密后的数据:%u %u\n",v[0],v[1]);
uint32_t tmp[2] = {0};
for(int i = 0; i < sizeof(encode_data)/sizeof(uint32_t); i+=2)
{
tmp[0] = encode_data[i];
tmp[1] = encode_data[i+1];
decipher(r,tmp, key);
printf("%s",tmp);
}
return 0;
}DASCTF{Don't_forget_to_drink_tea}]]>
直接爆破
#include <stdio.h>
#include <string.h>
int main()
{
int enc[] =
{
0xE8, 0x80, 0x84, 0x08, 0x18, 0x3C, 0x78, 0x68, 0x00, 0x70,
0x7C, 0x94, 0xC8, 0xE0, 0x10, 0xEC, 0xB4, 0xAC, 0x68, 0xA8,
0x0C, 0x1C, 0x90, 0xCC, 0x54, 0x3C, 0x14, 0xDC, 0x30
};
char key[] = "NewStarCTF";
for(int i =0; i < 29; i++)
{
for(int j = 33; j < 127; j++)
{
int tmp = j;
if(tmp >= 'A' && tmp <= 'Z')
{
tmp = (tmp - 52) % 26 + 65;
}
else if(tmp >= '0' && tmp <= '9')
{
tmp = (tmp - 45) % 10 + 48;
}
else if(tmp >= 'a' && tmp <= 'z')
{
tmp = (tmp - 89) % 26 + 97;
}
tmp += key[i % strlen(key)];
tmp = ~tmp;
tmp = (unsigned char)(tmp * 52);
if(tmp == enc[i])
{
if((j >= 'A' && j <= 'Z') || (j >= 'a' && j <= 'z'))
{
printf("%c", j);
break;
}
}
}
}
return 0;
}BruteForceIsAGoodwaytoGetFlag]]>
思路就是爆破
要注意windows的srand()函数和Linux的srand()函数不一样,要放在linux中运行
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned char enc[] = {
0xEE, 0xE6, 0xD7, 0xB2, 0x8A, 0xAB, 0x13, 0x35, 0x02, 0x7B,
0xC9, 0xB9, 0x9C, 0xBA, 0xED, 0x2E, 0xBD, 0x4F, 0xFA, 0xEE,
0xC8, 0xF8, 0xE4, 0x16, 0x82, 0x63, 0x3B, 0x98, 0xF4, 0x14,
0x30, 0x38, 0x07, 0x36, 0x84, 0x3D, 0x0C, 0x36, 0x32, 0xEA,
0x55, 0xA6
};
unsigned char Table[] = {
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01,
0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D,
0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4,
0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7,
0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E,
0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB,
0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB,
0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C,
0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C,
0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D,
0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A,
0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3,
0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A,
0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E,
0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9,
0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9,
0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99,
0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
};
srand(0x7261745377654E);
int v4 = 0;
int v3 = 0;
char flag[43] = {0};
for(int j = 0; j < 42; j++ )
{
v4 = rand();
for(int i = 32; i < 127; i++)
{
v3 = i;
if(enc[j] == Table[(16 * ((v3 + v4 % 255) >> 4) + 15) & (v3 + v4 % 255)])
{
flag[j] = i;
break;
}
}
}
printf("%s", flag);
return 0;
}flag{B8452786-DD8E-412C-E355-2B6F27DAB5F9}]]>
拿到题目,先使用exeinfo查壳

程序是无壳32位
使用ida打开,查看伪代码

大概过一遍
程序将用户输入保存在unk_4033D4
之后有个反调试,然后调用了sub_401042()函数
接下来是一个判断,判断flag是否正确,但是ida没有识别出来这个函数,应该是被加密了
跟进sub_401042()函数查看

这个函数对数组byte_403040进行了操作,这个数组就是判断flag时调用的函数
我们只要动调到sub_401042()函数执行完就可以看到验证flag的函数
因为程序有反调试,我们在检测反调试的地方下个断点

调试启动!!!
输入flag之后程序停在了跳转这边

jz是判断zf标志位来跳转的

我们只要修改zf标志位就能控制跳转,将zf改成1,在判断flag的的地方下个断点,继续运行

按f7于运行一步,双击进入byte_403040

ida已经识别出指令了,在函数头按P创建函数,再按f5查看伪代码

现在已经能看到flag的验证函数了
用户输入的数据异或0x11再加5等于加密字符串,我们只要将加密flag反正运算一下就能得到flag
接下来写exp
双击进入unk_403020,选中shift+e就能提取加密flag的数据

enc = [
0x7C, 0x82, 0x75, 0x7B, 0x6F, 0x47, 0x61, 0x57, 0x53, 0x25,
0x47, 0x53, 0x25, 0x84, 0x6A, 0x27, 0x68, 0x27, 0x67, 0x6A,
0x7D, 0x84, 0x7B, 0x35, 0x35, 0x48, 0x25, 0x7B, 0x7E, 0x6A,
0x33, 0x71
]
flag = ''
for i in range(32):
flag += chr((enc[i] - 5) ^ 0x11)
print(flag)flag{SMC_1S_1nt3r3sting!!R1ght?}]]>
拿到题目 使用exeinfo查看程序信息
是一个无壳32位程序

直接ida分析
v6是sub_401160函数的返回值
Text[v6] = 0 在c语言中字符串是以0结尾的 这里的意思是取v6的值为字符串长度
查看sub_401160函数的参数是Text &unk_402008 28

双击&unk_402008查看值
发现这是个数组

转换一下
是一个长度为176的数组

跟进sub_401160函数查看

继续跟进sub_401000函数
这个函数对Text进行了操作

运行程序查看
发现程序消息框的内容正好是28位 也就是sub_401160函数中的第三个参数 循环的次数
大胆猜想 每循环一次就处理一个&unk_402008中的字符
&unk_402008中有176个字符 去掉最后一位0 就是175分字符
我们只要把28次循环改成175次就可以得到flag

现在有两种解题思路
1.将程序的代码dump下来 将循环次数改成175
2.使用动调 直接将循环次数改成175
我选第二种方法(太懒了)
使用x32dbg打开程程序
发现内存地址和ida中的内存地址不一样

接下来计算偏移地址
找一个比较明显的特征
就这个push Output

在动调中搜索字符串

找到output双击进去

在动调中的内存地址为003E11EF
ida中的地址为004011EF
将这两个地址相减就是偏移地址了

在ida中找到push 1Ch
复制他的内存地址
在动调中跳转到这个地址-20000



右键这个地址->在内存窗口中转到->选定的地址

右键这个1C->修改

修改成AF(十进制的175)

按f9运行程序

flag{I_a_M_t_h_e_e_n_C_o_D_i_n_g@flare-on.com}使用exeinfo查壳
是一个无壳32位的程序

直接上ida
直接看main函数
将用户的输入保存到buffer[]
使用sub_401260函数处理buffer[]
Str1指向处理之后sub_401260的返回值
最后比较Str1和Str2的值

跟进sub_401260函数查看
瞅一眼代码 发现很眼熟 看着像base64
继续往下看

看到了byte_413000 双击进去查看
发现了对base64的编码表进行了修改

到这里题目的逻辑已经很清晰了
直接写脚本跑flag
import base64
def main():
string1 = "ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
encode = "x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q"
print(base64.b64decode(encode.translate(str.maketrans(string1,string2))))
if __name__ =="__main__":
main()flag{sh00ting_phish_in_a_barrel@flare-on.com}下载题目,首先使用exeinfo查壳

查出来是upx的壳 尝试使用脱壳工具脱壳
脱完壳使用ida打开

看到了jnz 有call了一个错误的函数 很明显是一个花指令
选中那一行 在ida中点击edit->Path program->Change program bytes

将e8修改成90
在汇编指令中e8是call 90是nop
修改好之后选中红色区域 按p 创建函数 就可以发现 现在可以反汇编了

按f5进行反汇编

发现程序判断用户输入是否为a d s w 对asc_408078 和 dword_40807C进行操作
然后通过题目名maze翻译过来就是迷宫 猜测通过用户的输入 移动一个坐标 找到flag

查看asc_408078的初始值是7

查看dword_40807C 初始值是0
经过一系列操作之后要使asc_408078 == 5 和 dword_40807C == -4
也是就是起始点(7,0)->终点(5,-4)

shift+f12查找字符串 看到了一个很可疑的字符串 看似是个迷宫
把它复制出来
从坐标得知 F 在第-4行 也就是说 f上面还有4行(0,-1,-2,-3)
F是-4行第5个, 也就是前面还有5个 排一下版

flag{ssaaasaassdddw}
]]>