前言
virink的web题
最简单的尝试,右键查看源码,师傅友好的指出了:
index.js底部的
也只是no_flag而已。
这里发现服务器是用OpenResty服务器,这里pcat科普下:OpenResty是一个基于Nginx与Lua的高性能Web平台,其内部集成了大量精良的Lua库、第三方模块以及大多数的依赖项。
最后回到最初:
这里存在一个uploads文件夹,访问下
里面左边preview的格式是/preview?f= 尝试文件包含漏洞
由于是使用OpenResty,尝试包含nginx的配置文件,默认是
/etc/nginx/conf.d/default.conf
发现../
被过滤,尝试下双写可以绕过
/preview?f=....//....//....//....//....//....//etc..//nginx..//conf.d..//default.conf
尝试读取preview.lua源码
/preview?f=....//preview.lua
这里要注意是lua的替换是正则替换。
尝试
/preview?f=....//....//....//....//....//....//....//f1ag_Is_h3re
未果,最后是
/preview?f=....//....//....//....//....//....//....//f1ag_Is_h3re..//flag
Ps:virink师傅开源了项目(代码有修改):
https://github.com/CTFTraining/virink_2019_web_files_share
郁离歌的web题
代码很熟悉,用gopher协议读取数据库内容即可。这里直接提供virink师傅写的一个payload:
ttps://raw.githubusercontent.com/virink/ctflog/master/ctf473831530/yulige_exp.py
政博的windows驱动题
wp作者:天河
感谢这题带我走进了新世界的大门。
首先给了两个附件一个是驱动文件.sys,逻辑不是很复杂。
先看和驱动交互的程序,User为Processor,然后输入key。
打开驱动成功的情况下:
上面的操作是将数据发送给驱动,控制码是0x22a444,用于发送数据
上面的操作是用来接收返回的数据判断发送的key正确与否,控制码是0x226448
剩下的就是看驱动的部分:
以上是主要的处理程序
这部分明显是比较结果,我们追查一下dword_403264从哪来的
这个V5==0x22a444和用来和驱动交互的程序发送数据的部分对上了。
猜测v6是数据debug后,也确实如此。
之后的过程把数据经过
处理后存放的地址放在了dword_403264这个位置,进入函数观察处理过程,是一个base58的过程,对比较字符串进行解码
脚本如下:
# -*- coding:utf8 -*-
a='KkYWdwLPHPjzTfpEwLa4qQMxGC'
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
__b58base = len(__b58chars)
def b58encode(v):
""" encode v, which is a string of bytes, to base58.
"""
long_value = int(v.encode("hex_codec"), 16)
result = ''
while long_value >= __b58base:
div, mod = divmod(long_value, __b58base)
result = __b58chars[mod] + result
long_value = div
result = __b58chars[long_value] + result
# Bitcoin does a little leading-zero-compression:
# leading 0-bytes in the input become leading-1s
nPad = 0
for c in v:
if c == ' ':
nPad += 1
else:
break
return (__b58chars[0] * nPad) + result
def b58decode(v):
""" decode v into a string of len bytes
"""
long_value = 0L
for (i, c) in enumerate(v[::-1]):
long_value += __b58chars.find(c) * (__b58base ** i)
result = ''
while long_value >= 256:
div, mod = divmod(long_value, 256)
result = chr(mod) + result
long_value = div
result = chr(long_value) + result
nPad = 0
for c in v:
if c == __b58chars[0]:
nPad += 1
else:
break
result = chr(0) * nPad + result
return result
if __name__ == "__main__":
print b58decode("KkYWdwLPHPjzTfpEwLa4qQMxGC")
得到的结果,花括号换为英文的即可。
Ps: 其他详细驱动的使用调试之类的可以参照政博师傅给的readme
天河的安卓题
wp作者:天河
主界面只有个简单的输入框,处理逻辑的核心存在于so中。
可以看到init中上来就把一大段代码异或了
被处理过的这段代码encode函数是加密的核心逻辑,经过异或处理还原真实的代码之后一切逻辑很明了,把输入的字符串经过encode函数处理之后和2ifuiJ4F6VMwaY8ATEr7db/=字符串进行比较
相等即可通过验证。
Encode函数是base64编码修改的,换了个表
“lmnopqrABCDEdefghFGXYZabcijkstuvwxyz012STUVW3456789+/HIJKLMNOPQR”
在每轮加密都会把表前后颠倒即可,
即table=table[::-1]
脚本如下:
#include<stdio.h>
#include<string.h>
#include <cstring>
void Reverse(char *s,int n){
for(int i=0,j=n-1;i<j;i++,j--){
char c=s[i];
s[i]=s[j];
s[j]=c;
}
}
static const char *ALPHA_BASE1 = "lmnopqrABCDEdefghFGXYZabcijkstuvwxyz012STUVW3456789+/HIJKLMNOPQR";
char *encode(const char *buf, const long size, char *base64Char) {
char ALPHA_BASE[] = "lmnopqrABCDEdefghFGXYZabcijkstuvwxyz012STUVW3456789+/HIJKLMNOPQR";
int a = 0;
int i = 0;
while (i < size) {
Reverse(ALPHA_BASE,64);
char b0 = buf[i++];
char b1 = (i < size) ? buf[i++] : 0;
char b2 = (i < size) ? buf[i++] : 0;
int int63 = 0x3F; // 00111111
int int255 = 0xFF; // 11111111
base64Char[a++] = ALPHA_BASE[(b0 >> 2) & int63];
base64Char[a++] = ALPHA_BASE[((b0 << 4) | ((b1 & int255) >> 4)) & int63];
base64Char[a++] = ALPHA_BASE[((b1 << 2) | ((b2 & int255) >> 6)) & int63];
base64Char[a++] = ALPHA_BASE[b2 & int63];
}
switch (size % 3) {
case 1:
base64Char[--a] = '=';
case 2:
base64Char[--a] = '=';
}
return base64Char;
}
char *decode(const char *base64Char, const long base64CharSize, char *originChar, long originCharSize) {
//char *ALPHA_BASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char ALPHA_BASE[] = "lmnopqrABCDEdefghFGXYZabcijkstuvwxyz012STUVW3456789+/HIJKLMNOPQR";
int toInt[128] = {-1};
/*for (int i = 0; i < 64; i++) {
toInt[ALPHA_BASE[i]] = i;
}*/
int int255 = 0xFF;
int index = 0;
for (int i = 0; i < base64CharSize; i += 4) {
Reverse(ALPHA_BASE,64);
for (int i = 0; i < 64; i++) {
toInt[ALPHA_BASE[i]] = i;
}
int c0 = toInt[base64Char[i]];
int c1 = toInt[base64Char[i + 1]];
originChar[index++] = (((c0 << 2) | (c1 >> 4)) & int255);
if (index >= originCharSize) {
return originChar;
}
int c2 = toInt[base64Char[i + 2]];
originChar[index++] = (((c1 << 4) | (c2 >> 2)) & int255);
if (index >= originCharSize) {
return originChar;
}
int c3 = toInt[base64Char[i + 3]];
originChar[index++] = (((c2 << 6) | c3) & int255);
}
return originChar;
}
int main()
{
char *base="2ifuiJ4F6VMwaY8ATEr7db/=";
char c[256];
decode(base,strlen(base),c,17);
printf("%s",c);
}
Question 5 将会在10月左右开放,敬请期待。
ps. CTF学习交流群跟ChaMd5安全团队无关,本文乃投稿。
招新小广告
ChaMd5 ctf组 长期招新
尤其是crypto+reverse+pwn+合约的大佬
原文始发于微信公众号(ChaMd5安全团队):CTF学习交流群 第四期writeup大放送