C#反射实现简单的插件系统

如果用过一些优秀的开源或是非开源的应用软件,就会发现这些软件的一个很大的优势就是其开放性,任何有能力的人都可以为其开发不同的插件来增强其的功能。比如著名的foobar2000,Vim和TotalCommander等等。 C#的反射可以用来实现一个简单的插件系统。思路很简单,我们创建一个解决方案,包含三个工程,一个为我们的软件MyApplication,一个为插件接口IPlugin,一个为具体的插件MyPlugin。插件系统的基本思路是我们用一个接口类库,来定义我们软件可以使用的插件必须实现的方法签名。然后我们的软件MyApplication通过引用该IPlugin dll来动态调用,而具体的实现插件MyPlugin则引用该接口来实现具体的方法。这样我们的应用程序就能在不知道具体插件的情况下调用插件了。。 结构图如下: 关键代码也就是通过对程序集载入。搜索到对应接口的实现类。然后调用即可。 Assembly a = Assembly.LoadFrom(AssemblyName); foreach (Type t in a.GetTypes()) { if (t.GetInterface("IMyFunction") != null) { try { IMyFunction pluginclass = Activator.CreateInstance(t) as IMyFunction; pluginclass.doSomething(); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } } 运行结果: 源码下载:PluginSystem.zip

2013-02-21 · 1 min · bystander

利用反射转换对象list到csv

扒自一工程。。可以学习一下.net中反射的简单用法 /// <summary> /// Take object List as input and export to csv which will be prompt save as dialog /// </summary> /// <typeparam name="T"> Type of object</typeparam> /// <param name="listToExport"> Object list to export</param> /// <param name="seperateChar"> character to use as scv separator</param> public static string ExportListToCSV<T>( List<T> listToExport, string seperateChar) { Int32 success = 0; StringBuilder export = new StringBuilder(); try { string seperator = "" ; StringBuilder builder = new StringBuilder(); //获取表头的 PropertyInfo[] fieldInfo = listToExport[0].GetType().GetProperties(); foreach (PropertyInfo col in fieldInfo) { if (!col.PropertyType.FullName.Equals("System.Data.EntityKey") && !col.PropertyType.FullName.Equals("System.Data.EntityState" )) { builder.Append(seperator).Append(col.Name); seperator = seperateChar; } } export.AppendLine(builder.ToString()); foreach (T dataItem in listToExport) { PropertyInfo[] allProperties = dataItem.GetType().GetProperties(); seperator = ""; StringBuilder builderTmp = new StringBuilder(); //真正求数据域的 foreach (PropertyInfo thisProperty in allProperties) { if (!thisProperty.PropertyType.FullName.Equals("System.Data.EntityKey") && !thisProperty.PropertyType.FullName.Equals("System.Data.EntityState" )) { object value = thisProperty.GetValue(dataItem, null); String propetyValue = (value == null ? String.Empty : value.ToString()); builderTmp.Append(seperator).Append(propetyValue); seperator = seperateChar; } } ++success; export.AppendLine(builderTmp.ToString()); } } catch (Exception ex) { throw ex; } return export.ToString(); } if (!thisProperty.PropertyType.FullName.Equals("System.Data.EntityKey") && !thisProperty.PropertyType.FullName.Equals("System.Data.EntityState")) ...

2013-02-02 · 1 min · bystander

recon-ng开源信息探测框架

作者:bystander 博客:http://leaver.me 微博:http://t.qq.com/lazystander 论坛:法客论坛 首发。转载什么的请注明出处。起码给我留个链接啥的嘛。 首先介绍一下。这个工具是国外刚刚发布的。主要用来渗透前的信息探测。使用类似Metasploit 主要有 Auxiliary: 这个模块查询主机信息泄漏页。进行hash反查,模糊名称精确,检查某个email是否密码泄漏,域名解析ip等 Contacts: 这个模块探测和某一公司有关的人员的信息,主要包括 LinkedIn 和Jigsaw 这两个模块。得到的信息可以被Auxiliary模块使用,如果和Social Engineer Toolkit(社会工程学工具集,这个工具已经发布了。是开源的。大家可以看看),一起。效果强大。 Hosts: 这个用来获取站点子域名。。包括使用baidu。Google bing等。。效果相当强大。 Output: 这个模块用来创建输出报表 Pwnedlist: 这个模块不是得shell的。他可通过 Pwnedlist.com 提供的api,如果这个网站被入侵过。那么可以直接获得其他黑客泄漏的帐号密码。。(需要去 Pwnedlist.com 注册) 安装方法: bt下直接 git clone https://[email protected]/LaNMaSteR53/recon-ng.git 然后有可能提示输入密码,好象是随便输一个用来保护版本控制。。我输的是toor。。 然后就安装好了。输入 cd recon-ng 然后 ./recon-ng.py 首先查看有哪些模块。输入 modules 图一 我以获取子域名为例,通过我前面的介绍你已经知道了hosts模块里的所有模块基本都是干这事的。我用里面的baidu模块来说明。你也可以使用bing等,, 输入命令 load hosts::baidu 图二 刚开始你可能不清楚这个模块的说明。那么继续输入info即可查看模块的详细说明 要开始使用。我们输入 options 和Metasploit很像把。可以查看要使用需要的配置。 图三 看表,会发现有三行。第一行是标题,第二行是域名设置,第三行是输出。这个current value也就是当前值已经为true。所以不用设置。req的意思是是否必须设置。我们输入 baidu.com就是你的目标了。 set domain baidu.com 就会从百度的结果里提取百度的子域名信息了。要开始。我们输入 run 图四 更多希望大家发掘吧。我抛砖。求引玉。

2013-02-02 · 1 min · bystander

操作系统中的页面置换算法

最近读完了《现代操作系统》。页面置换算法的读书笔记。其他的笔记慢慢整理一下在博客做个备份。 虚拟内存的基本思想:每个程序都拥有自己的内存空间,这个空间被分割成很多块,每一块称为一页/页面,每一页有连续的地址范围,这些页被映射到物理内。 页面置换算法 1.最优页面置换算法,每个页面都可以用在该页面首次被访问前所需要执行的指令数作为标记。因此我们选择标记最大的页面,也就是把不愉快的事情往后拖延。但是,唯一的问题是无法实现。 2.最近未使用页面置换算法。系统每一个页面设置两个状态位,当页面被访问时设置R位,当被修改时设置M位,包含在页表项中,初始时,都被设置0,R被定期地清零,以区别最近没有被访问和被访问的页面。NRU算法随机的从类编号最小的非空类中挑选一个页面淘汰之, 根据R和W可以将页面分为4类 0没有被访问,没有被修改/1没有被访问,被修改/2已被访问,没有被修改/3已被访问,已被修改。第一类只有在定期清R的时候才会出现。 隐含的意思是,淘汰一个没有被访问的已修改页面要比淘汰一个被频繁使用的干净页面要好。 3.先进先出置换,找出最先进入的替换掉,很少单独使用 4.第二次机会页面置换算法。FIFO可能将经常使用的页面置换出来。为此,检查最老页面的r位,如果R为0,则既老又没有被使用,则就置换掉,如果是1,就清0,放在链表尾,修改装入时间为最新。继续搜索。 5.时钟页面置换算法,第二次机会算法经常要在链表中移动页面,更好的方法是将页面保存在一个类似钟面的环形链表中,表针指向最老的页面。发生缺页时,如果R是0就 淘汰该页面,并插入新页面,然后表针前移,如果是1,就清除R并前移,直到找到一个R位为0的页面。这也是时钟的由来 [![](/images/e198f5889716b00f06a452789f0c413474927e87.jpg)](http://leaverimage.b0.upaiyun.com/32235_o.jpg) 6.最近最少使用页面置换算法。在发生缺页时,置换未使用时间最长的页面,这个策略称为LRU,最简单的一个实现策略是有一个64位计数器,每条指令执行完加1.每个页表项必须有一个足够容纳这个计数器值的域,每次访问内存后,将C值保存到被访问页面的页表项,一旦中断,检查所有页面项的计数器值,找到最小的即可。 7.NFU最不常用算法,是LRU的软件模拟实现。每个页面与一个软件计数器管理。初值为0,每次时钟中断时,操作系统扫描内存中的所有页面,将每个页面中的R位值加到他的计数器上,计数器的值即为访问的频繁程度。该算法的问题是记住的事情太多,如果第一次执行扫描的时间最长。比如第一次某个页面的值很大。这个很大的值会影响到下一次扫描,结果操作系统将置换有用的页面而不是不再使用的页面。 8.修改一下NFU:R位被加进之前,将计数器右移一位,同时将R加到计数器的左端。即为老化算法 9.工作集页面置换算法。一个进程当前正在使用的页面的集合称作他的工作集。基本思路是找出一个不在工作集中的页面并淘汰它。 10.工作集时钟页面置换算法。基于时钟算法,并且使用了工作集信息。 页面调度算法总结; 最好的两种算法是老化算法和工作集时钟算法,分别基于LRU和工作集。具有良好的页面调度性能。

2013-01-30 · 1 min · bystander

C# 基础知识系列文章索引

清理GR的加星标项目。分享来自博客园 zhili 的C#基础系列文章。 C#基础知识系列终于告了一个段落了, 本系列中主要和大家介绍了C#1.0到C# 4.0中一些重要的特性,刚开始写这个专题的初衷主要是我觉得掌握了C#这些基础知识之后,对于其他任何的一门语言都是差不多的,这样可以提高朋友们对其他语言的掌握,以及可以让大家更加迅速地掌握.NET的新特性, 并且相信这个系列对于找工作的朋友也是很有帮助的,因为很多公司面试都很看重基础知识是否扎实,是否对C#有一个全面的认识和理解,所以很多公司面试都会问到一些C#基础概念的问题,例如,经常面试会问:你是如何理解委托的,如何理解匿名函数等问题。 然而这个系列中并没有介绍COM互操作性的内容以及.Net 4.5中的一些新特性,所以后面将会对这两个方面的内容进行补充,由于这个系列托的太久了(大概也有3个月吧),所以就先告一段落的,后面将会带来.NET互操作性系列的介绍。下面就为这个系列文章做一个索引,方便大家收藏和查找。 C#基础知识系列索引 C#1.0 1. 深入解析委托——C#中为什么要引入委托 2. 委托本质论 3. 如何用委托包装多个方法——委托链 4. 事件揭秘 5. 当点击按钮时触发Click事件背后发生的事情 C# 2.0 6. 泛型基础篇——为什么引入泛型 7. 泛型深入理解(一) 8. 泛型深入理解(二) 9. 深入理解泛型可变性 10. 全面解析可空类型 11. 匿名方法解析 12. 迭代器 C# 3.0 13. 全面解析对象集合初始化器、匿名类型和隐式类型 14. 深入理解Lambda表达式 15. 全面解析扩展方法 16. Linq介绍 C# 4.0 17. 深入理解动态类型 从C#的所有特性可以看出,C#中提出的每个新特性都是建立在原来特性的基础上,并且是对原来特性的一个改进, 做这么多的改进主要是为了方便开发人员更好地使用C#来编写程序,是让我们写更少的代码来实现我们的程序,把一些额外的工作交给编译器去帮我们做,也就是很多人说微软很喜欢搞语法糖的意思(语法糖即让编译器帮我们做一些额外的事情,减少开发人员所考虑的事情,使开发人员放更多的精力放在系统的业务逻辑上面。),大家从C# 3中提出的特性中可以很好的看出这点(指的是玩语法糖),C#3中几乎大部分特性都是C#提供的语法糖,从CLR层面来说(指的是增加新的IL指令),C# 3并没有更新什么,C# 4中提出的动态类型又是建立在表达式树的基础上,包括Linq也是建立在表达式树的基础上,所以每个特性都是层层递进的一个关系。相信C#后面提出的新特性将会更加方便我们开发程序,感觉所有语言的一个统一的思想都是——写更少的代码,却可以做更多的事情。但是我们不能仅仅停住于知道怎么使用它,我们还应该深入研究它的背后的故事,知道新特性是如何实现的和原理。用一句说就是——我们要知其然之气所以然,学习知识应该抱着刨根问底的态度去学习,相信这样的学习方式也可以让大家不感到心虚,写出的程序将会更加自信。

2013-01-27 · 1 min · bystander

现代操作系统的调度

这几天在读《现代操作系统》,想起当时学这门课的时候,并没有感觉那么爽,现在通读这本书,知识的过渡性和结构性令我叹服。感受操作系统的魅力吧。 批处理系统中的调度: 1.先来先服务 2.最短作业优先 只有在所有的作业都可以同时运行(也即同时到达)的情况下,最短作业优先算法才是最优化的。 3.最短剩余时间优先-最短作业优先的抢占式版本。调度算法总是选择剩余时间最短的那个进程运行,注意,运行时间必须提前掌握,当一个新的作业到达时,其整个时间同当前进程的剩余时间做比较,如果更少。就运行新进程。可以使新的短作业获得良好的服务。 交互式系统的调度 1.轮转调度。 最古老,最简单,最公平切使用最广,每个进程被分配一个时间片。如果进程在时间片结束之前阻塞或结束,则CPU立即切换。调度程序只是维护一张可运行进程列表,当进程用完它的时间片后,就被移到队列的末尾。时间片太短会导致进程切换过多,降低CPU效率,设置的太长又引起对短的交互请求的响应时间变长。通常20-50ms算合理。 2.优先级调度 为了防止高优先级进程无休止的运行下去,可以在一个时钟中断里降低当前进程的优先级,如果这导致该进程的优先级低于次高优先级的进程,则切换或者也可以赋予每个进程一个时间片。可以和轮转调度一起工作,设置每个优先级上有多个进程。优先运行高优先级,并未高优先级上的进程按照轮转换着运行,如果高优先级没了。就进入到较低优先级。。。问题是如果不偶尔对优先级进行调整,则可能发生饥饿现象。 3.多级队列 CTSS的设计者发现为CPU密集型进程设置较长的时间片比频繁的分给他们很短的时间片更为高效(减少了交换次数),但长时间的进程又会影响响应时间,方法是设立优先级类,最高优先级类里的进程运行1个时间片。次高运行2个。以此类推。当一个进程用完分配的时间片后,被移动到下一类。大致算法都是用于讨好交互用户和进程,而不惜牺牲后台进程 //故事:可以采用只要终端上有Enter键按下,就将该终端上的进程移到最高优先级类。假设当前进程急需交互,但是。一个人发现了。大家都开始用。。。理论和实际差异太大。。哈哈 4.最短进程优先 这个很好立即,但难点在于如何找出最短的那个。一种方法是根据过去的行为推测。假设每个命令执行时间为T0,下一次运行时间为T1,则可以根据aT0+(1-a)T1来估计时间。。a被用来决定尽快忘掉老的运行时间还是记住它。这种算法成为老化算法。通常选a=1/2 5.保证调度 就是保证每个用户获得cpu的1/n,系统需要跟踪进程的cpu时间,他实际获得如果多于应该获得的。则转向实际获得小于应该获得的。 6.彩票调度 保证调度很难实现,而彩票调度算法是向进程提供各种系统资源的彩票。一旦需要做出一项调度决策时,就随机抽出一张彩票。谁获得谁就上。比如视频服务器,可以为不同的帧速率提供不同的彩票。然后分配cpu 7.公平分享调度 这个就考虑到了进程的所有者。需要我们定义公平的含义。是保证每个用户只占用的时间相等还是其他了。 实时系统的调度: 可以分为硬实时和软实时,前者必须满足绝对的截止时间,后者则可以容忍一些。用户级线程系统是不知道的。用户级和内核级的差异主要在性能,用户级需少量的机器指令,而内核级需要很多的。过程。采用轮转和优先级调度更常见一些。 //操作系统的大神们太强大了。哲学家进餐问题居然可以通过拿起左边叉子以后,检测右边是否可用,如果不可用,则等待一个随机的时间。这种方案是可行的。在极少的情况下不可用。。

2013-01-24 · 1 min · bystander

社工字典生成工具

在家无聊写了这个工具,主要是为了防止自己这一直写随笔把本行忘了。。也熟悉一下代码。。暂时不放源代码了。以后改的好一点再发吧。 作者:bystander 博客:http://leaver.me 转载请注明出处! 涉及到的东西有: 1.C#隐藏TabControl的header部分,前面的文章有介绍 2.获取窗体全部的某一类控件(这个无聊的话抽象出一个通用的方法出来,以后就可以直接用了) /// <summary> /// 获取所有的文本框控件 /// </summary> /// <param name="control"></param> /// <returns></returns> private List<TextBox> GetAllControls(Control control) { foreach (Control con in control.Controls) { if (con.Controls.Count > 0) { GetAllControls(con); } else if (con is TextBox) { tBoxList.Add(con as TextBox); } } return tBoxList; } 3.文件操作 4.字符串操作 反正很简单,主要就是写的时候思路要清晰。知道大部分使用密码的规则。处理一下生日格式。否则后面很麻烦。。相应的验证也比较少。界面依然毫无美感。。 总结: 现在发现在控件命名上越来越顺利了。自我感觉良好。后面慢慢的要开始尝试使用学到的一些新的技术点。。 下载:社工字典生成工具

2013-01-21 · 1 min · bystander

C#隐藏TabControl标签栏

今天考过了微软的那个70-562和70-536的考试。然后下午把软件体系结构的作业做了。然后看了一下栈溢出,我博客首页右侧的那个就是我的栈溢出id了。。 然后就看到了这个问题。这个问题。我曾经遇到过。貌似大家知道比较多的是两种。第一种就是设置大小。 tabControl1.SizeMode = TabSizeMode.Fixed; tabControl1.ItemSize = new Size(0, 1); 但是这样你注意看的话,左上角有个小的瑕疵。这个没办法的。。还有一种比较低级但还算有效的方法就是在设计的时候将TabControl向上移动。运行以后就会遮住了。 我当时不过取巧了。好像就用的第二种。。今天看到这个题目的时候,就做了下标记。刚才去看。大牛已经给出答案了。就是自己继承一个TabControl控件。重写 void WndProc(ref Message m) 方法,在方法里拦截系统消息。 using System; using System.Windows.Forms; class TablessControl : TabControl { protected override void WndProc(ref Message m) { // Hide tabs by trapping the TCM_ADJUSTRECT message if (m.Msg == 0x1328 && !DesignMode) m.Result = (IntPtr)1; else base.WndProc(ref m); } } 具体用法。就是在你的项目里新建一个类文件。然后把上面的代码拷进去。然后编译一下。就会在工具箱里多出一个TablessControl控件。拖进来即可使用。当然你也可以自定义一个用户控件。都不是事。这个控件设计时标签页可见。运行时由于拦截了信息消息。标签栏就不可见了。堪称完美。。

2013-01-11 · 1 min · bystander

图的遍历(C#)

讲的非常好的一篇文章。感谢abatei,直接收藏分享之。 图的存储结构 图的存储结构除了要存储图中各个顶点的本身的信息外,同时还要存储顶点与顶点之间的所有关系(边的信息),因此,图的结构比较复杂,很难以数据元素在存储区中的物理位置来表示元素之间的关系,但也正是由于其任意的特性,故物理表示方法很多。常用的图的存储结构有邻接矩阵、邻接表、十字链表和邻接多重表。 8.2.1 邻接矩阵表示法 对于一个具有n个顶点的图,可以使用n*n的矩阵(二维数组)来表示它们间的邻接关系。图8.10和图8.11中,矩阵A(i,j)=1表示图中存在一条边(Vi,Vj),而A(i,j)=0表示图中不存在边(Vi,Vj)。实际编程时,当图为不带权图时,可以在二维数组中存放bool值,A(i,j)=true表示存在边(Vi,Vj),A(i,j)=false表示不存在边(Vi,Vj);当图带权值时,则可以直接在二维数组中存放权值,A(i,j)=null表示不存在边(Vi,Vj)。 图8.10所示的是无向图的邻接矩阵表示法,可以观察到,矩阵延对角线对称,即A(i,j)= A(j,i)。无向图邻接矩阵的第i行或第i列非零元素的个数其实就是第i个顶点的度。这表示无向图邻接矩阵存在一定的数据冗余。 图8.11所示的是有向图邻接矩阵表示法,矩阵并不延对角线对称,A(i,j)=1表示顶点Vi邻接到顶点Vj;A(j,i)=1则表示顶点Vi邻接自顶点Vj。两者并不象无向图邻接矩阵那样表示相同的意思。有向图邻接矩阵的第i行非零元素的个数其实就是第i个顶点的出度,而第i列非零元素的个数是第i个顶点的入度,即第i个顶点的度是第i行和第i列非零元素个数之和。 由于存在n个顶点的图需要n2个数组元素进行存储,当图为稀疏图时,使用邻接矩阵存储方法将出现大量零元素,照成极大地空间浪费,这时应该使用邻接表表示法存储图中的数据。 8.2.2 邻接表表示法 图的邻接矩阵存储方法跟树的孩子链表示法相类似,是一种顺序分配和链式分配相结合的存储结构。邻接表由表头结点和表结点两部分组成,其中图中每个顶点均对应一个存储在数组中的表头结点。如这个表头结点所对应的顶点存在相邻顶点,则把相邻顶点依次存放于表头结点所指向的单向链表中。如图8.12所示,表结点存放的是邻接顶点在数组中的索引。对于无向图来说,使用邻接表进行存储也会出现数据冗余,表头结点A所指链表中存在一个指向C的表结点的同时,表头结点C所指链表也会存在一个指向A的表结点。 有向图的邻接表有出边表和入边表(又称逆邻接表)之分。出边表的表结点存放的是从表头结点出发的有向边所指的尾顶点;入边表的表结点存放的则是指向表头结点的某个头顶点。如图8.13所示,图(b)和(c)分别为有向图(a)的出边表和入边表。 以上所讨论的邻接表所表示的都是不带权的图,如果要表示带权图,可以在表结点中增加一个存放权的字段,其效果如图8.14所示。 【注意】:观察图8.14可以发现,当删除存储表头结点的数组中的某一元素,有可能使部分表头结点索引号的改变,从而导致大面积修改表结点的情况发生。可以在表结点中直接存放指向表头结点的指针以解决这个问题(在链表中存放类实例即是存放指针,但必须要保证表头结点是类而不是结构体)。在实际创建邻接表时,甚至可以使用链表代替数组存放表头结点或使用顺序表存代替链表存放表结点。对所学的数据结构知识应当根据实际情况及所使用语言的特点灵活应用,切不可生搬硬套。 【例8-1 AdjacencyList.cs】图的邻接表存储结构 using System; using System.Collections.Generic; public class AdjacencyList<T> { List<Vertex<T>> items; //图的顶点集合 public AdjacencyList() : this(10) { } //构造方法 public AdjacencyList(int capacity) //指定容量的构造方法 { items = new List<Vertex<T>>(capacity); } public void AddVertex(T item) //添加一个顶点 { //不允许插入重复值 if (Contains(item)) { throw new ArgumentException("插入了重复顶点!"); } items.Add(new Vertex<T>(item)); } public void AddEdge(T from, T to) //添加无向边 { Vertex<T> fromVer = Find(from); //找到起始顶点 if (fromVer == null) { throw new ArgumentException("头顶点并不存在!"); } Vertex<T> toVer = Find(to); //找到结束顶点 if (toVer == null) { throw new ArgumentException("尾顶点并不存在!"); } //无向边的两个顶点都需记录边信息 AddDirectedEdge(fromVer, toVer); AddDirectedEdge(toVer, fromVer); } public bool Contains(T item) //查找图中是否包含某项 { foreach (Vertex<T> v in items) { if (v.data.Equals(item)) { return true; } } return false; } private Vertex<T> Find(T item) //查找指定项并返回 { foreach (Vertex<T> v in items) { if (v.data.Equals(item)) { return v; } } return null; } //添加有向边 private void AddDirectedEdge(Vertex<T> fromVer, Vertex<T> toVer) { if (fromVer.firstEdge == null) //无邻接点时 { fromVer.firstEdge = new Node(toVer); } else { Node tmp, node = fromVer.firstEdge; do { //检查是否添加了重复边 if (node.adjvex.data.Equals(toVer.data)) { throw new ArgumentException("添加了重复的边!"); } tmp = node; node = node.next; } while (node != null); tmp.next = new Node(toVer); //添加到链表未尾 } } public override string ToString() //仅用于测试 { //打印每个节点和它的邻接点 string s = string.Empty; foreach (Vertex<T> v in items) { s += v.data.ToString() + ":"; if (v.firstEdge != null) { Node tmp = v.firstEdge; while (tmp != null) { s += tmp.adjvex.data.ToString(); tmp = tmp.next; } } s += "\r\n"; } return s; } //嵌套类,表示链表中的表结点 public class Node { public Vertex<T> adjvex; //邻接点域 public Node next; //下一个邻接点指针域 public Node(Vertex<T> value) { adjvex = value; } } //嵌套类,表示存放于数组中的表头结点 public class Vertex<TValue> { public TValue data; //数据 public Node firstEdge; //邻接点链表头指针 public Boolean visited; //访问标志,遍历时使用 public Vertex(TValue value) //构造方法 { data = value; } } } AdjacencyList<T>类使用泛型实现了图的邻接表存储结构。它包含两个内部类,Vertex<Tvalue>类(109~118行代码)用于表示一个表头结点,Node类(99~107)则用于表示表结点,其中存放着邻接点信息,用来表示表头结点的某条边。多个Node用next指针相连形成一个单链表,表头指针为Vertex类的firstEdge成员,表头结点所代表的顶点的所有边的信息均包含在链表内,其结构如图8.12所示。所不同之处在于: l Vertex类中包含了一个visited成员,它的作用是在图遍历时标识当前节点是否被访问过,这一点在稍后会讲到。 ...

2013-01-06 · 4 min · bystander

SQL注入中的WAF绕过技术

作者:bystander 博客:http://leaver.me 论坛:法克论坛 目录 1.大小写绕过 2.简单编码绕过 3.注释绕过 4.分隔重写绕过 5.Http参数污染(HPP) 6.使用逻辑运算符 or /and绕过 7.比较操作符替换 8.同功能函数替换 9.盲注无需or和and 10.加括号 11.缓冲区溢出绕过 1. 大小写绕过 这个大家都很熟悉,对于一些太垃圾的WAF效果显著,比如拦截了union,那就使用Union UnIoN等等。绕过 2. 简单编码绕过 比如WAF检测关键字,那么我们让他检测不到就可以了。比如检测union,那么我们就用%55 也就是U的16进制编码来代替U, union写成 %55nION,结合大小写也可以绕过一些WAF,你可以随意替换一个或几个都可以。。 也还有大家在Mysql注入中比如表名或是load文件的时候,会把文件名或是表明用16进制编码来绕过WAF都是属于这类。 3. 注释绕过 这种情况比较少,适用于WAF只是过滤了一次危险的语句,而没有阻断我们的整个查询 > /?id=1+union+select+1,2,3/* 比如对于上面这条查询,WAF过滤了一次union和select,那么我们在之前在写一个注释的语句,让他把注释里面的过滤掉,,并不影响我们的查询。。 所以绕过语句就是: > /?id=1/*union*/union/*select*/select+1,2,3/* 还有一种和注释有关的绕过: 比如 > index.php?page_id=-15 /*!UNION*/ /*!SELECT*/ 1,2,3,4…. 可以看到,只要我们把敏感词放到注释里面,注意,前面要加一个! 4. 分隔重写绕过 还是上面的例子,适用于那种WAF采用了正则表达式的情况,会检测所有的敏感字,而不在乎你写在哪里,有几个就过滤几个。。 我们可以通过注释分开敏感字,这样WAF的正则不起作用了,而带入查询的时候并不影响我们的结果 > /?id=1+un/**/ion+sel/**/ect+1,2,3-- 至于重写绕过,适用于WAF过滤了一次的情况,和我们上传aaspsp马的原理一样,我们可以写出类似Ununionion这样的。过滤一次union后就会执行我们的查询了 > ?id=1 ununionion select 1,2,3-- 5. Http参数污染(HPP) 比如我们有这样的语句: > /?id=1 union select+1,2,3+from+users+where+id=1-- 我们可以重复一次前面的id值添加我们的值来绕过,&id=会在查询时变成逗号 > /?id=1 union select+1&id=2,3+from+users+where+id=1-- 这种情况成功的条件比较多,取决于具体的WAF实现。。 再给出一个例子说明用法 > /?id=1/**/union/*&id=*/select/*&id=*/pwd/*&id=*/from/*&id=*/users-- 具体分析的话就涉及到查询语句的后台代码的编写了。 比如服务器是这样写的: > select * from table where a=".$_GET['a']." and b=".$_GET['b']." limit ".$_GET['c']; 那我们可以构造这样的注入语句: > /?a=1+union/*&b=*/select+1,pass/*&c=*/from+users-- 最终解析为: > select * from table where a=1 union/* and b=*/select 1,pass/*limit */from users-- 可以看到,这种方式其实比较适合白盒测试,而对于黑盒渗透的话,用起来比较麻烦。但是也可以一试。 6. 使用逻辑运算符 or /and绕过 > /?id=1+OR+0x50=0x50 > /?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),1,1)))=74 顺便解释一下第二句话,从最里面的括号开始分析,select+pwd+from+users+limit+1,1 这句是从users表里查询pwd字段的第一条记录,比如是admin, 然后mid(上一句),1,1就是取admin的第一个字符,也就是a, lower(上一句)就是把字符转换为小写, 然后ascii就是把a转换成ascii码,看等不等于74. 7. 比较操作符替换 包括!= 不等于,<>不等于,< 小于,>大于,这些都可以用来替换=来绕过, 比如上一个例子,要判断是不是74,假设=被过滤,那么我们可以判断是不是大于73,是不是小于75,然后就知道是74了。。很多WAF都会忘了这个。 8. 同功能函数替换 Substring()可以用mid(),substr()这些函数来替换,都是用来取字符串的某一位字符的。 Ascii()编码可以用hex(),bin(),也就是16进制和二进制编码替换 Benchmark() 可以用sleep()来替换,这两个使用在基于延时的盲注中,有机会给大家介绍 如果连这些都屏蔽了,还有一种新的方法 ...

2013-01-06 · 1 min · bystander