StarGate
这道题因为自己各种基础知识不牢固的原因写了很久,细节上的知识需要自己不断地积累,也觉得自己写代码太烂了!!!太菜了!!!
使用nc连接靶机,返回得到文件的base64加密内容
提取出这个base64加密的内容,放入在线网站之中bse64解密,得到的是一个elf文件
将这个elf文件放入ida之中,通过字符串定位到关键的代码位置
分析流程(欧拉路径问题)
题目之中给了提示 “寻找欧拉路径”
对于一个给定的图,怎样判断是否存在着一个恰好包含了所有的边,并且没有重复的路径?这就是一笔画问题。用图论的术语来说,就是判断这个图是否是一个能够遍历完所有的边而没有重复。这样的图现称为欧拉图。这时遍历的路径称作欧拉路径(一个环或者一条链),如果路径闭合(一个圈),则称为欧拉回路
通过catflag这个字符串定位到一个相关联的函数
if语句之中的判断条件是判断走过了所有的路径,每个变量参数代表的是某路径是否走过的标志位
查看字符串表,图中红色方框中的字符串就能够定位到一个函数之中,每个函数之中的逻辑都一样
字符串定位到的函数:每次输入一个字符串,相当于到达某一个对应的函数,跳转就是一条边,每条边的表示方法是dword_41D1C这样的形式
走过所有的边,最后catflag的函数:
所以这个就是一个一笔画问题
因为这是一个图的问题,从代码之中提取出边对应的字符串的表示方法和它对应调用的函数,对应的函数之中又有和这条边相连的能够走的路径,我们要dump出所有的边,并且给按照代码将这些边连接起来生成一个图,再将这个图作为参数传入欧拉路径的算法之中,得到走的路径,按照这个路径再向这个靶机之中传入得到的路径
re模块的常量(属性)
连接服务器得到elf文件
用pwn连接服务器,将服务器返回的进行base64加密的elf文件进行解密,并且保存
1 2 3 4 5 6 7 8 9
| # 获得连接服务器得到的脚本 from pwn import * import base64 context.log_level = 'debug' io = remote("node4.buuoj.cn",25305) io.recvuntil('Gate') code = io.recvuntil('==end==') with open("code","wb") as f: f.write(base64.b64decode(code[:-8]))
|
ida反编译得到c语言文件
将elf文件放入ida64之中(使用ida64的7.5版本),然后使用File->Produce File->Creat C File将反编译的c语言代码dump下来
图的生成
正则搜索code.c文件之中的代码,得到相对应的图(点和点的对应关系),并将其写入graph.txt文件之中
生成图的方法:
使用正则表达式搜索到所有具有如下if语句的函数,每个这样的函数将是数组之中的一个元素
将所有这些函数名集合成一个数组,这个数组就是所有的点
这些函数名跳转到另外一个函数就作为一个边(每个函数名也就是每个点都会有一个对应的字符串),遍历每个函数就能够得到所有的这些边,需要注意的是因为是无向图,同一条边会被表示两次
将数组之中这些函数的索引作为每个点的表示(因为c语言脚本之宗数组的起点是1,所以所有的索引需要加一之后写入)
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
| import re with open("code.c","r") as f: codes = f.read()
passwords = re.findall('if \( !strcmp\("(.*?)", s2\) && dword_[0123456789ABCDEF]{6} == 1 \)',codes) print(len(passwords))
funcnames_pass = re.findall("(sub_[0123456789ABCDEF]{6}\(\));\n exit\(0\);",codes) print(len(funcnames_pass))
functions = re.findall("__int64 sub_[0123456789ABCDEF]{6}\(\)\n{\n char s2\[40\];.*?Wrong password",codes,re.DOTALL)
funcnames = [] for obj in functions: funcname = re.findall("__int64 (sub_[0123456789ABCDEF]{6}\(\))",obj)[0] funcnames.append(funcname) print(funcnames)
dic_child_func = {} dic_child_str = {}
graph = [] for obj in functions: funcname = re.findall("__int64 (sub_[0123456789ABCDEF]{6}\(\))",obj)[0] child_funcnames = re.findall("(sub_[0123456789ABCDEF]{6}\(\));\n exit\(0\);",obj) child_str = re.findall('if \( !strcmp\("(.*?)", s2\) && dword_[0123456789ABCDEF]{6} == 1 \)',obj) dic_child_func[funcname] = child_funcnames dic_child_str[funcname] = child_str for obj0 in child_funcnames: tem = [] tem.append(funcnames.index(funcname)) tem.append(funcnames.index(obj0)) graph.append(tem) print(graph) print(len(graph)) with open("graph.txt",'w') as f: f.write(str(len(graph))+" "+str(len(funcnames))) f.write("\n") for i in range(len(graph)): f.write(str(graph[i][0]+1)+" "+str(graph[i][1]+1)) f.write("\n")
|
欧拉路径算法(fleury算法)
用c语言读取graph.txt之中点的对应关系,初始化图,得到对应的数组,然后找出欧拉路径,将欧拉路径写入到map.txt文件之中
注意,因为刻画出来的无向图之中,一条边被表示了两次,所以在初始化数组的时候,需要判断一下该条边是否被赋值过,如果已经被赋值了,就不用再次赋值了
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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
| #include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<vector> using namespace std;
const int N = 1005; int n, m, flag, top, sum, du[N], ans[5005], map[N][N]; FILE* fpwrite;
void dfs(int x) { ans[++top] = x; for(int i = 1; i <= n; i++) { if(map[x][i] >= 1) { map[x][i]--; map[i][x]--; dfs(i); break; } } }
void fleury(int x) { top = 1; ans[top] = x; while(top > 0) { int k = 0; for(int i = 1; i <= n; i++) { if(map[ans[top]][i] >= 1) {k = 1; break;} } if(k == 0) {
fprintf(fpwrite,"%d",ans[top]); fprintf(fpwrite,"\n"); top--; } else if(k == 1) { top--; dfs(ans[top+1]); } } }
int main() { FILE* fpread; fpread = fopen("D:\\re\\buuctf\\practice\\1\\graph.txt","r"); fpwrite = fopen("D:\\re\\buuctf\\practice\\1\\map.txt","w");
if(fpread == NULL) { printf("file is error!!!"); return -1; } fscanf(fpread,"%d",&m); fscanf(fpread,"%d",&n); memset(du, 0, sizeof(du)); memset(map, 0, sizeof(map)); for(int i = 1; i <= m; i++) { int x, y; fscanf(fpread,"%d%d",&x,&y); if (map[x][y] == 0){ map[x][y]++; map[y][x]++; du[x]++; du[y]++; }
} flag = 1; sum = 0; for(int i = 1; i <= n; i++) { if(du[i] % 2 == 1) { sum++; flag = i; } } if(sum == 0 || sum == 2) fleury(flag);
printf("Success!");
return 0; }
|
用于交互的字符串数组
(图中表示的那个函数是输出cat 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
| theMap = [] theStrmap = [] with open("map.txt","r") as f: for line in f: theMap.append(int(line.strip('\n'))-1) print(len(theMap)) theFistFunc = funcnames[theMap[0]] theFistFuncStr = passwords[funcnames_pass.index(theFistFunc)] theStrmap.append(theFistFuncStr) for i in range(len(theMap)-1): theFucName = funcnames[theMap[i]] theNextFuncName = funcnames[theMap[i+1]] theIndex = dic_child_func[theFucName].index(theNextFuncName) theStrmap.append(dic_child_str[theFucName][theIndex]) print(len(theStrmap))
print("第一步所到达的函数的字符串:"+theFistFuncStr) print("到达最后一步函数输入的字符串:"+theStrmap[len(theStrmap)-1])
theCodeFinalStr = re.findall(" v2 = __readfsqword\(0x28u\);\n if \( !dword_[0123456789ABCDEF]{6}\n.*?printf\(\"Now you in universe ([a-zA-Z]{1,})",codes,re.DOTALL)
if theFistFuncStr == theCodeFinalStr: theStrmap.reverse() for i in range(len(theStrmap)): io.sendline(theStrmap[i]) io.recvuntil(":") io.interactive()
|
脚本汇总
python的脚本代码(汇总):需要按照需求在相应的位置停顿
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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| from pwn import * import base64 context.log_level = 'debug' io = remote("node4.buuoj.cn",25305) io.recvuntil('Gate') code = io.recvuntil('==end==') with open("code","wb") as f: f.write(base64.b64decode(code[:-8]))
input("请先dump出code.c 之后想要继续请按回车") import re with open("code.c","r") as f: codes = f.read()
passwords = re.findall('if \( !strcmp\("(.*?)", s2\) && dword_[0123456789ABCDEF]{6} == 1 \)',codes) print(len(passwords))
funcnames_pass = re.findall("(sub_[0123456789ABCDEF]{6}\(\));\n exit\(0\);",codes) print(len(funcnames_pass))
functions = re.findall("__int64 sub_[0123456789ABCDEF]{6}\(\)\n{\n char s2\[40\];.*?Wrong password",codes,re.DOTALL)
funcnames = [] for obj in functions: funcname = re.findall("__int64 (sub_[0123456789ABCDEF]{6}\(\))",obj)[0] funcnames.append(funcname) print(funcnames)
dic_child_func = {} dic_child_str = {}
graph = [] for obj in functions: funcname = re.findall("__int64 (sub_[0123456789ABCDEF]{6}\(\))",obj)[0] child_funcnames = re.findall("(sub_[0123456789ABCDEF]{6}\(\));\n exit\(0\);",obj) child_str = re.findall('if \( !strcmp\("(.*?)", s2\) && dword_[0123456789ABCDEF]{6} == 1 \)',obj) dic_child_func[funcname] = child_funcnames dic_child_str[funcname] = child_str for obj0 in child_funcnames: tem = [] tem.append(funcnames.index(funcname)) tem.append(funcnames.index(obj0)) graph.append(tem) print(graph) print(len(graph)) with open("graph.txt",'w') as f: f.write(str(len(graph))+" "+str(len(funcnames))) f.write("\n") for i in range(len(graph)): f.write(str(graph[i][0]+1)+" "+str(graph[i][1]+1)) f.write("\n")
input("请先执行c语言代码,之后继续请按回车")
theMap = [] theStrmap = [] with open("map.txt","r") as f: for line in f: theMap.append(int(line.strip('\n'))-1) print(len(theMap)) theFistFunc = funcnames[theMap[0]] theFistFuncStr = passwords[funcnames_pass.index(theFistFunc)] theStrmap.append(theFistFuncStr) for i in range(len(theMap)-1): theFucName = funcnames[theMap[i]] theNextFuncName = funcnames[theMap[i+1]] theIndex = dic_child_func[theFucName].index(theNextFuncName) theStrmap.append(dic_child_str[theFucName][theIndex]) print(len(theStrmap))
print("第一步所到达的函数的字符串:"+theFistFuncStr) print("到达最后一步函数输入的字符串:"+theStrmap[len(theStrmap)-1])
theCodeFinalStr = re.findall(" v2 = __readfsqword\(0x28u\);\n if \( !dword_[0123456789ABCDEF]{6}\n.*?printf\(\"Now you in universe ([a-zA-Z]{1,})",codes,re.DOTALL)
if theFistFuncStr == theCodeFinalStr: theStrmap.reverse() for i in range(len(theStrmap)): io.sendline(theStrmap[i]) io.recvuntil(":") io.interactive()
flag{76efc0a7-eba1-4b83-a6d7-dce9cf17f4bd}
|