StarGate
这道题因为自己各种基础知识不牢固的原因写了很久,细节上的知识需要自己不断地积累,也觉得自己写代码太烂了!!!太菜了!!!
使用nc连接靶机,返回得到文件的base64加密内容

提取出这个base64加密的内容,放入在线网站之中bse64解密,得到的是一个elf文件

将这个elf文件放入ida之中,通过字符串定位到关键的代码位置

分析流程(欧拉路径问题)
题目之中给了提示 “寻找欧拉路径”
对于一个给定的图,怎样判断是否存在着一个恰好包含了所有的边,并且没有重复的路径?这就是一笔画问题。用图论的术语来说,就是判断这个图是否是一个能够遍历完所有的边而没有重复。这样的图现称为欧拉图。这时遍历的路径称作欧拉路径(一个环或者一条链),如果路径闭合(一个圈),则称为欧拉回路
通过catflag这个字符串定位到一个相关联的函数
if语句之中的判断条件是判断走过了所有的路径,每个变量参数代表的是某路径是否走过的标志位

查看字符串表,图中红色方框中的字符串就能够定位到一个函数之中,每个函数之中的逻辑都一样

字符串定位到的函数:每次输入一个字符串,相当于到达某一个对应的函数,跳转就是一条边,每条边的表示方法是dword_41D1C这样的形式 

走过所有的边,最后catflag的函数:

所以这个就是一个一笔画问题
因为这是一个图的问题,从代码之中提取出边对应的字符串的表示方法和它对应调用的函数,对应的函数之中又有和这条边相连的能够走的路径,我们要dump出所有的边,并且给按照代码将这些边连接起来生成一个图,再将这个图作为参数传入欧拉路径的算法之中,得到走的路径,按照这个路径再向这个靶机之中传入得到的路径
re模块的常量(属性)

连接服务器得到elf文件
用pwn连接服务器,将服务器返回的进行base64加密的elf文件进行解密,并且保存
| 12
 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,所以所有的索引需要加一之后写入) 
| 12
 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 rewith 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文件之中
注意,因为刻画出来的无向图之中,一条边被表示了两次,所以在初始化数组的时候,需要判断一下该条边是否被赋值过,如果已经被赋值了,就不用再次赋值了
| 12
 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的函数,图中标注的字符串是我们需要到达的字符串)

| 12
 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的脚本代码(汇总):需要按照需求在相应的位置停顿
| 12
 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}
 
 | 
