C#代码分析器(C#游戏代码注入)
来源:互联网 发布:php is numeric 漏洞 编辑:程序博客网 时间:2024/06/01 17:02
简介
在进行C#代码注入的过程中,写的比较复杂的逻辑,但是reflector注入只能一个个函数来进行,而且添加paramter非常复杂,这里做了一个简单的代码分析器,帮助所有代码集中到一个函数中。
虽然感觉上比较简单,但做的过程中,花费了大半天的时间,这里把遇到的问题总结一下,给大家后续开发一些启示。
理论上C语言格式的都可以用这个解析把多个函数包含在一个函数里面
Reflector注入过程
- 1 导入相应的dll
- 2 tools decompile。 点右键 replaceWithCode。
- 3 子类添加函数基类,然后写函数。
- 4 在dll上右键Reflexil -> SaveAs相关dll即可。
遇到的问题
因为relector一次只支持注入一个函数,而我们写的显示代码是有多个函数的。
即使新加入一个类,也需要在这个类里面单独加入各个函数。
同时代码里面有互相的嵌套,而且有返回值和各个参数,如果单个的加非常的麻烦,而且reflector不支持返回值,相关的值只能放入输出参数,和原有的代码就大大违背了。
所以这里写了一个简单的代码分析器,用这个解析把多个函数包含在一个函数里面。
代码格式
首先读入的代码要编译通过
需要一些简单的约束:
- 1子函数必须有返回值,且返回值不能用和次子函数的参数相同。只有一个返回的出口。上支持上任意返回类型,只是父函数必须调用一下子函数返回的值。
- 2 调用函数的参数中不支持嵌套调用自己写的函数。
- 3 除非是返回值,否则临时变量需要自行设的是unique的。否则会重复定义。
- 4 “{}”这种单独占一行,一般C#编辑器会自动解析成这样。
- 5 函数不能循环调用,解析会进入循环。
- 6 目前只支持+=和+,如果需要其他运算符,在tpl_func_split中加。 特殊的运算序列没有做支持,当时这个分析器只是为了输出日志方便用的。
输入格式
//(joint为已知的Joint数据结构) public string A(string p) { string tmpA = "add a" + p; return tmpA; } public string B(Jointjoint, string c) { string tmp = "add b\n"; tmp += A(joint.format) + joint; return tmp; } public void Jump() { string tmp = "start ===\n"; //tmp += "A " + A("12"); //tmp += B("34", "12"); tmp += " A B" + A("12") + B(joint, "c") + A("34"); }
输出格式
会经过代码分析器分析为:
public void Jump() { string tmp ="start ===\n"; string _result_6_ ="add a"+"12"; string _result_7_ ="add b\n"; string _result_8_ ="add a"+joint.format; _result_7_ +=_result_8_+joint; string _result_9_ ="add a"+"34"; tmp +=" A B"+_result_6_+_result_7_+_result_9_; }
思路
整体思路:
分治法。
每个函数有多行语句,每行语句包含多个函数,经过相互调用就相当于减了一层调用。无论有多少层调用,最终都可以解析为只包含一层可以输出的序列。
如 tmp += A(cc)
就会变为:
<<A相关的表达式,同时更新所有的输入为cc输出为_result_1_>>
Tmp += _result_1_;
1 将每个函数解析为结构FuncDesc, 存入一个整体的FUNC_DICT中。
class FuncDesc(object): def __init__(self): self.params_list = [] self.func_desc = [] self.func_desc_split = [] self.func_name = "" self.out_name = ""
2 每个out_name和params_list的表示都用一个特殊的完全不同的字符串代替。方便以后在调用的时候,整体替换。
3 其中每个func_desc表示一行代码。
每行代码再生成一个结构
class DescFuncSplit(object): def __init__(self, desc_str): self.desc_str = desc_str # (type, funcname, params), type0:normal, 1 func self.func_list = [] self.opeartor_list = [] self.has_semicolon = False
4 在调用到单个func_desc的时候,判断各个函数,调用到FuncDesc,赋值params和return_value。
在FuncDesc在依次调用每个func_desc_split。最终会得到一系列字符串。
经过相互调用,最终会在最简单层中停止:
如code中A
这一系列的字符串就是最后希望得到的函数。
输出是最终的函数内部的内容。
需要自己加上函数头,可以放在C#编辑器里面format一下。
下附代码
#-*- coding:utf-8 -*-"""python XX.py inputfilename.cs out_func_name第一个参数是要读入的文件名称第二个参数是要输出的函数名"""import os, sysimport reTOTAL_NUM = 0;FUNC_DICT = {}def GetIndexNum(): global TOTAL_NUM TOTAL_NUM += 1 return TOTAL_NUMdef replacer(search_obj, replace_str): groups = search_obj.groups() return groups[0] + replace_str + groups[1] def change_descs(init_str, change_param, replace_param): cal = r"(\W)%s(\W)" % change_param; replacer2 = lambda search_obj: replacer(search_obj, replace_param) return re.sub(cal, replacer2, init_str) class DescFuncSplit(object): def __init__(self, desc_str): self.desc_str = desc_str # (type, funcname, params), type0:normal, 1 func self.func_list = [] self.opeartor_list = [] self.has_semicolon = False def debug_info(self): print "==============" print "debug_info: ", self.desc_str print self.func_list print self.opeartor_list def get_split_out_result(self, param_dict): print "get_split_out_result" , param_dict total_len = len(self.func_list) out_str = "" out_list = [] for idx in xrange(total_len): func_tuple = self.func_list[idx] if func_tuple[0] == 0: out_str += func_tuple[1] else: func_result_name = "_result_%s_" % GetIndexNum() func_desc = FUNC_DICT[func_tuple[1]] params = func_tuple[2] new_params = [] for new_param in params: for k,v in param_dict.items(): new_param = new_param.replace(k, v) new_params.append(new_param) tmp_list = func_desc.get_end_result(new_params, func_result_name) out_list.extend(tmp_list) out_str += func_result_name if idx < total_len - 1: out_str += self.opeartor_list[idx] if self.has_semicolon: out_str += ";" out_str += "\n" out_list.append(out_str) return out_list def tpl_func_split(self): total_split = [] out_str = "" if self.desc_str.find("+=") >= 0: self.func_list.append((0, self.desc_str[:self.desc_str.find("+=")])) out_str = self.desc_str[self.desc_str.find("+=") + 2:] self.opeartor_list.append("+=") elif self.desc_str.find("=") >= 0: self.func_list.append((0, self.desc_str[:self.desc_str.find("=")])) out_str = self.desc_str[self.desc_str.find("=") + 1:] self.opeartor_list.append("=") else: out_str = self.desc_str #鍘婚櫎瀛楃涓插唴閮ㄧ殑+ -> _ total_len = len(out_str) idx = 0 while(idx < total_len): if out_str[idx] == "\"": idy = idx + 1 while(idy < total_len): if out_str[idy] == "+": out_str[idy] = "_" if out_str[idy] == "\"": idy += 1 break idy += 1 idx = idy else: idx += 1 func_split = out_str.split("+") for sp in func_split: sp = sp.strip() if sp[-1] == ";": sp = sp[:-1].strip() self.has_semicolon = True if sp[0] == "\"": self.func_list.append((0, sp)) self.opeartor_list.append("+") elif sp[-1] == ")": l = sp.find("(") funcname = sp[:l].strip() if not FUNC_DICT.has_key(funcname): self.func_list.append((0, sp)) self.opeartor_list.append("+") continue params_str = sp[l+1:-1] params_split = params_str.split(",") params = [] for param in params_split: param = param.strip() params.append(param) self.func_list.append((1, funcname, params)) self.opeartor_list.append("+") else: self.func_list.append((0, sp)) self.opeartor_list.append("+") return class FuncDesc(object): def __init__(self): self.params_list = [] self.func_desc = [] self.func_desc_split = [] self.func_name = "" self.out_name = "" def debug_info(self): print "========" print "params_list:", self.params_list print "func_desc:" print self.func_desc print "func_name: %s, out_name: %s" % (self.func_name, self.out_name) def get_func_name(self, fs): fp = fs.split("(") tmp_list = fp[0].split(" ") self.func_name = tmp_list[-1]; fp[1] = fp[1].replace(")", "") tmp_list = fp[1].split(",") for tmp in tmp_list: tt = tmp.split(" ") for idtt in xrange(len(tt) - 1, -1, -1): if tt[idtt].strip() != "": self.params_list.append(tt[idtt].strip()) break def change_params_to_unique(self): for params_key in xrange(len(self.params_list)): new_param = "_param_%s_" % GetIndexNum() param = self.params_list[params_key] self.params_list[params_key] = new_param for desc_key in xrange(len(self.func_desc)): desc = self.func_desc[desc_key] new_desc = change_descs(desc, param, new_param) self.func_desc[desc_key] = new_desc return def change_out_name_to_unique(self): return_desc = self.func_desc[-1] new_desc = return_desc.replace(";", "") if new_desc.find("return") < 0: return out_name = new_desc[new_desc.find("return") + 6:].strip() if out_name == "": self.func_desc.pop() return self.out_name = "_result_%s_" % GetIndexNum() for desc_key in xrange(len(self.func_desc)): desc = self.func_desc[desc_key] new_desc = change_descs(desc, out_name, self.out_name) self.func_desc[desc_key] = new_desc self.func_desc.pop() return def change_desc_value_to_func_split(self): for desc in self.func_desc: desc_func_split = DescFuncSplit(desc) desc_func_split.tpl_func_split() self.func_desc_split.append(desc_func_split) def get_end_result(self, params, func_result_name): print "get_end_result ", params, func_result_name if self.out_name != "" and func_result_name == "": print "error %s has no func_result_name" % self.func_name raise 1 if len(params) != len(self.params_list): print "error %s params error %s %s" % (self.func_name, self.params_list, params) raise 1 param_dict = {} for idx in xrange(len(self.params_list)): param_dict[self.params_list[idx]] = params[idx] out_list = [] for func_split in self.func_desc_split: func_split.debug_info() func_str_list = func_split.get_split_out_result(param_dict) for func_str in func_str_list: out_str = func_str; for k,v in param_dict.items(): out_str = out_str.replace(k,v) out_list.append(out_str) if self.out_name != "": for idx in xrange(len(out_list)): out_str = out_list[idx] out_list[idx] = out_str.replace(self.out_name, func_result_name) return out_listdef main(filename, out_func_name): f = open(filename, "r") lines = f.readlines(); f.close(); total_line = len(lines) for line in lines: if line.startswith("{") or line.endswith("}"): if len(line.strip()) != 1: print "not strip one line", line raise 1 cur_num = 0 while(cur_num < total_line): if lines[cur_num].find("public") < 0: cur_num += 1 continue func_desc = FuncDesc() func_desc.get_func_name(lines[cur_num]) cur_num += 1 while(cur_num < total_line): if lines[cur_num].strip() == "{": break cur_num += 1 cur_num += 1 cur_left = 1 while(cur_num < total_line): if lines[cur_num].strip() == "{": cur_left += 1 if lines[cur_num].strip() == "}": cur_left -= 1 if cur_left == 0: break strip_line = lines[cur_num].strip() if strip_line != "" and not strip_line.startswith("//"): func_desc.func_desc.append(lines[cur_num]) cur_num += 1 FUNC_DICT[func_desc.func_name] = func_desc cur_num += 1 print FUNC_DICT.keys() for func_desc in FUNC_DICT.values(): func_desc.change_params_to_unique() func_desc.change_out_name_to_unique() func_desc.change_desc_value_to_func_split() func_desc.debug_info() if not FUNC_DICT.has_key(out_func_name): print "error outfuncname in readfile", filename return out_str_list = [] out_str_list = FUNC_DICT[out_func_name].get_end_result([], "") f = open("out.txt", "w") for out_str in out_str_list: f.write(out_str) f.close() if __name__ == "__main__": if len(sys.argv) < 3: print "please input: readfilename outfuncname" exit() out_func_name = sys.argv[2] filename = sys.argv[1] main(filename, out_func_name)
0 0
- C#代码分析器(C#游戏代码注入)
- C# 词法分析器(二)输入缓冲和代码定位
- C# 代码分析器 1.0 版开发完成
- C#的防范SQL注入代码!
- C#防SQL注入代码实现方法
- C#防SQL注入代码实现方法
- C# winform 防止sql注入代码
- 游戏进程注入代码
- 猜数游戏的 C#代码
- C#代码
- c#代码
- C#代码
- C#代码跟踪代码
- C#调用系统API实现内存注入的代码
- 网站安全性:C#防SQL注入代码的实现方法
- C#防SQL注入代码的三种方法
- C#防SQL注入代码的三种方法
- C#词法分析器之输入缓冲和代码定位的应用分析(二)
- 头文件,宏,extern
- Intellij IDEA中出现内存泄漏的问题
- PE框架——style的配置
- HPU 1276: QAQ and steel ball discs
- PE框架——使用工厂类生成序列号seq
- C#代码分析器(C#游戏代码注入)
- Java初始化总结【6、涉及到继承时 初始化顺序!!!!!】
- PE框架——template,command,chain
- Name、SuperClass、Constructor、Field、Method
- 面试总结
- .Net程序员学用Oracle系列(19):我知道的导出和导入
- PE框架——发送报文流程
- 2017年3月5日 周考3 解题报告
- 中游学院Swift语言视频教程swift培训视频