wdnmd B64 [攻防世界]
#problem.py #!/usr/bin/python2 #from flag import flag from base64 import b64decode from SocketServer import ThreadingTCPServer from sys import argv from binascii import hexlify, unhexlify import SocketServer import os flag = 'flag{123456789}'#本地调试 N = 8 MAX_TRIES = 1024 PAD = 64 welcome = "Welcome! :-)\n" menu = "What would you like to do:\n\t1: supply encoded input,\n\t2: tell me my secret\n> " def gen_secret(): return os.urandom(N) def crypt(s1, s2): return "".join(map(lambda c: chr(((ord(c[0])^ord(c[1]))+PAD)%256), zip(s1,s2))) b64chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/" def decode(s, secret): enc = "" s = crypt(s, secret) for c in s: if c in b64chars: enc+=c if len(enc) % 4 == 1: enc = enc[:-1] while len(enc) % 4 != 0: enc+="=" return b64decode(enc) class B64Handler(SocketServer.BaseRequestHandler): def setup(self): self.tries = 0 self.secret = gen_secret() def handle(self): self.request.send(welcome) for i in range(MAX_TRIES): self.request.send("Round number: {}\n{}".format(i, menu)) if self.request.recv(2)[0] == "1": self.request.send("What would you like me to decode?\n> ") answer = self.request.recv(len(self.secret)) decoded = decode(answer, self.secret) self.request.send("Alright, here is your answer: {}\n".format(decoded)) else: self.request.send("Alright, what is my secret (hex encoded)?\n> ") answer = self.request.recv(2*len(self.secret)+1).rstrip() if answer==hexlify(self.secret): self.request.send("Well done, here is your flag: {}\n".format(flag)) else: self.request.send("This was not what I was looking for. :-(\n") break self.request.send("Bye!\n") def main(): SocketServer.ThreadingTCPServer.allow_reuse_address = True if len(argv) < 2: print("Usage: {} <PORT>".format(argv[0])) else: LOCAL_PORT = int(argv[1]) s = SocketServer.ThreadingTCPServer(("", LOCAL_PORT), B64Handler) try: s.serve_forever() except KeyboardInterrupt: print("shutting down") s.shutdown() s.socket.close() if __name__ == "__main__": main()
可以看到这个server拥有两个功能,一个是将你发送过去的字符和secret运算 ,如果有符合base64字符的就返回
另一个是发送hex形式的secret 然后server返回flag
这道题有个小技巧
需要让对方返回最少四个字节才能根据一位判定,因为只有超过四个字节才不会被丢弃字符
from pwn import * import string list1 = string.printable import os #context.log_level = 'debug' p = remote('192.168.1.1',8088)#服务ip和端口 p.recvuntil('> ') p.sendline('1') p.recvuntil('> ') p.send('0'*8) p.recvuntil('answer: ') str1 = p.recvline()[:-1] while len(str1)<4: p.close() p = remote('192.168.170.1',8088) p.recvuntil('> ') p.sendline('1') p.recvuntil('> ') p.send('0'*8) p.recvuntil('answer: ') str1 = p.recvline()[:-1] len_num = len(str1) #print 'str1 = ',repr(str1) base_enc = str1.encode('base64').split('=')[0] #print base_enc flag = list('11111111') str3 = '' for i in range(8): p.sendline('1') str3 = '0'*i+'\x00'+'0'*(7-i) p.send(str3) p.recvuntil('answer: ') str2 = p.recvline()[:-1] if len(str2)<len_num: flag[i]='0' #print flag test_6 = 0 while "".join(flag).count('0')<6: for i in range(8): p.sendline('1') str3 = '0'*i+os.urandom(1)+'0'*(7-i) p.send(str3) p.recvuntil('answer: ') str2 = p.recvline()[:-1] if len(str2)<len_num: flag[i]='0' #print flag index_1 = flag.index('1') flag[index_1] = '0' str3 = '00000000' for i in range(0xff): mid = str3[:index_1]+chr(i)+str3[index_1+1:] p.sendline('1') p.send(mid) p.recvuntil('answer: ') str2 = p.recvline()[:-1] if len(str2)==5: #print '5555555555555555' break #print 'mid =',repr(str2) index_2 = flag.index('1') for i in range(0xff): last = mid[:index_2]+chr(i)+mid[index_2+1:] p.sendline('1') p.send(last) p.recvuntil('answer: ') str2 = p.recvline()[:-1] if len(str2)==6: #print '666666666666666666' break #print 'last =',repr(last) #print 'str2 =',repr(str2) #print 'b64str2 =',repr(str2.encode('base64')) p.sendline('2') sec = '' for i,j in zip(last,str2.encode('base64')): sec += chr(((ord(j)-64)%256)^ord(i)) p.sendline(sec.encode('hex')) p.interactive()