menu Alkaid #二进制初学者 / 网络安全 / 大龄CTF退役选手
2019年3月安恒平台周周练的做题思路分享
112 浏览 | 2019-04-04 | 分类:CTF | 标签:CTF

很久没写WP了,稍微记录下自己的做题过程:

Crypto

0x01 Ordinary keyboard

这是一道安恒18年11月份的密码原题:

题目提示是凯撒,但是我没按提示来做,首先根据题目将明文和密文对应起来做一个表,如下所示:

数字不会发生变化,直接写脚本,替换一下:

from string import maketrans

a='iloveyoublogwechat}{flag'
b="+p)g$_)'hp)uA$ezr&,.spru"
c='spru.r5sf3h7660h7394e169699hffe0s0h$4,'
d=maketrans(b,a)

f=c.translate(d)
flag=[]
for i in range(len(c)):
	if c[i] == f[i] and ord(f[i])>57:
		print c[i],f[i]
		flag+='?'
	else:
		flag+=f[i]
print ''.join(flag)

结果为:

?是没有确定的值,可以把其他没用过的字母填上测试,最后测出来是d

 

0x02 RSA

利用openssl得到公钥中n和e的值:

openssl rsa -pubin -text -modulus -in pub.key

Exponent: 65537 (0x10001)
Modulus=C0332C5C64AE47182F6C1C876D42336910545A58F7EEFEFC0BCAAF5AF341CCDD
writing RSA key
-----BEGIN PUBLIC KEY-----
MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhAMAzLFxkrkcYL2wch21CM2kQVFpY9+7+
/AvKr1rzQczdAgMBAAE=

-----END PUBLIC KEY-----

得到n的值,直接到http://factordb.com分解一下得到p和q:

可以计算出d,最后利用pow(c,d,n)计算出m来,脚本如下:

#-*- coding:utf-8 -*-

import gmpy2
from gmpy2 import invert, iroot
from Crypto.PublicKey import RSA

def rsa1(n, p, q, e):
	assert n == p * q
	d = invert(e, (p - 1) * (q - 1))
	return d

with open('pub.key','r') as f:
	key=RSA.importKey(f)
	n=key.n
	e=key.e


p=285960468890451637935629440372639283459
q=304008741604601924494328155975272418463
print n
assert q*p==n

d=rsa1(n, p, q, e)

with open("flag.enc","rb") as f:
	c=f.read().encode('hex')
	c=int(c,16)
m=pow(c,d,n)
print hex(m)[3:].decode('hex')

 

0x03 DSA attack

之前没做过DSA这种非对称加密方式的题,这次好好学习了下新知识:

本题给出的message3和message4的签名中r是相同的,也就是说,这两个签名使用了相同的k,可以轻松解出私钥x,脚本如下:

#coding=utf8
from Crypto.PublicKey import DSA
import hashlib
import gmpy2
with open('./dsa_public.pem') as f:
    key = DSA.importKey(f)
    y = key.y
    g = key.g
    p = key.p
    q = key.q
f3 = open("packet3/message3", 'rb')
f4 = open("packet4/message4", 'rb')
data3 = f3.read()
data4 = f4.read()

m3 = int(hashlib.sha1(data3).hexdigest(), 16)

m4 = int(hashlib.sha1(data4).hexdigest(), 16)
print m3, m4
s3 = 0x1B474F2C1C9E85B72841AD84D9A871A11EF0F323
s4 = 0x0EA21858C18AA1EDF4058B6EB9E02B0176243658
r = 0x12E780EE8471DC3552572BB6E818F6D22CE16EA4
ds = s4 - s3
dm = m4 - m3
k = gmpy2.mul(dm, gmpy2.invert(ds, q))
k = gmpy2.f_mod(k, q)
tmp = gmpy2.mul(k, s3) - m3
x = tmp * gmpy2.invert(r, q)
x = gmpy2.f_mod(x, q)

flag=hex(int(x))[2:-1]
print flag
print hashlib.md5(flag.decode('hex')).hexdigest()

 

Misc

0x01 qr

直接一扫得到flag:

0x02 wireshark

在第二个流里就直接找到了:

 

0x03 百里挑一

首先搜到flag的位置,但是这只是flag的前半部分,还得继续找后半部分:

后半部分在第114个流里:

 

Web

0x01 WebScan

payload:
101.71.29.5:10009/index.php?act=about&file=/etc/httpd/conf/httpd.conf

 

0x02 刀塔

使用敏感文件泄露扫描,发现有www.zip

flag.php里有明文flag

0x03 美男子

在源代码里发现提示,有index.phps:

<?php
include 'global.php';

function AttackFilter($StrKey,$StrValue,$ArrReq){  
    if(is_array($StrValue))
    {
        $StrValue=implode($StrValue);
    }
    if (preg_match("/".$ArrReq."/is",$StrtValue)==1){   
        print "holy shit!";
        exit();
    }      
} 

$filter = "union|select|from|where|join|sleep|benchmark|,|\(|\)";

foreach($_POST as $key=>$value){ 
    AttackFilter($key,$value,$filter);
}


if(!isset($_POST['key1']) || !isset($_POST['key2'])) {
    print <<<DBAPP

<img src='image/img.jpg' />
<!--index.phps-->
DBAPP;
    die;
}



$query = mysql_query("SELECT * FROM tb_ctf WHERE key1 = '{$_POST['key1']}'"); 
if(mysql_num_rows($query) == 1) { 
    $key = mysql_fetch_array($query);
    if($key['key2'] == $_POST['key2']) {
        print $flag;
    }else{
        print "Error!";
        }
}else{
    print "Error!";
}

代码审计一波,绕过注入,rollup回滚

 

REVERSE

0x01 Mysterious

IDA打开找到可疑字符串,直接跟到代码段:

可以看到输入的字符串中的v12是一段数字,v12+1=123,说明v12是122,v14为x,v15为y,v16为z,输入122xyz即可得到flag

 

0x02 findKey

这里连续使用了两个 push,需要把下面一个nop掉才能使用f5插件

根据库函数可以看出这里经过md5加密,直接写脚本解决异或,再将得到的md5去查下明文

得到值以后只需要动态调试时修改参数,就能得到最后的flag

或者根据代码逻辑写个脚本,再进行一次上面的异或操作,即可得到flag

a='0kk`d1a`55k222k2a776jbfgd`06cjjb'
b='SS'

md5=''
for i in range(len(a)):
	md5+=chr(ord(a[i])^ord(b[i%2]))
print md5

c=[0x57,0x5E,0x52,0x54,0x49,0x5F,0x1,0x6D,0x69,0x46,0x2,0x6E,0x5F,0x2,0x6C,0x57,0x5B,0x54,0x4C]
d='123321'

flag=''
for i in range(len(c)):
	flag+=chr(c[i]^ord(d[i%len(d)]))
print flag

 

 

0x03 CrackRTF

首先是第一个比较,和40个字节的字符串比较,使用sub_40100A,跟进去发现是sha1,而且前六位是数字,直接利用字符串和@DBApp拼接爆破得到前6位字符串:

import string
import itertools
import hashlib
import requests
import re

sha256enc='6E32D0943418C2C33385BC35A1470250DD8923A9'.lower()
key='@DBApp'
code = ''
strlist = itertools.product(string.digits, repeat=6)
 
for i in strlist:
    code = i[0] + i[1] + i[2] + i[3]+ i[4]+ i[5]
    encinfo = hashlib.sha1(code+key).hexdigest()
    if encinfo == sha256enc:
        print code

得到前六位123321

到达第二步:

这次变成了md5,爆破六位未知字符有点吃力,为了省事直接到google的gpu里用hashcat爆:

最后把字符串输入,直接打开生成的rtf文件获得flag

 

温柔正确的人总是难以生存,因为这世界既不温柔,也不正确

发表评论

email
web

全部评论 (暂无评论)

info 还没有任何评论,你来说两句呐!