首页
归档
友情链接
关于
Search
1
在wsl2中安装archlinux
271 阅读
2
从零开始配置 vim(15)——状态栏配置
159 阅读
3
nvim番外之将配置的插件管理器更新为lazy
145 阅读
4
2018总结与2019规划
138 阅读
5
PDF标准详解(五)——图形状态
116 阅读
软件与环境配置
读书笔记
编程
Thinking
FIRE
菜谱
翻译
登录
Search
标签搜索
c++
c
学习笔记
windows
文本操作术
编辑器
NeoVim
Vim
win32
emacs
读书笔记
elisp
VimScript
linux
文本编辑器
投资理财
Java
反汇编
OLEDB
数据库编程
Masimaro
累计撰写
396
篇文章
累计收到
32
条评论
首页
栏目
软件与环境配置
读书笔记
编程
Thinking
FIRE
菜谱
翻译
页面
归档
友情链接
关于
搜索到
396
篇与
的结果
2018-01-12
OLEDB数据源
数据源在oledb中指数据提供者,这里可以简单的理解为数据库程序。数据源对象代表数据库的一个连接,是需要创建的第一个对象。而数据源对象主要用于配置数据库连接的相关属性如连接数据库的用户名密码等等
2018年01月12日
41 阅读
0 评论
0 点赞
2018-01-07
《疯狂的程序员》读后感
之前我在新年计划中说,争取新加一点读书笔记的内容,为博客赚点流量,所以这是我的第一篇读书笔记,为什么选这本书呢?可以说这本书给我详细介绍了程序员的工作,世界观,使我对计算机编程有了浓厚的兴趣,同时它也给我指明了后面努力的方向。初次读这本书是在我大二那年,由一个同学推荐,后来在毕业之后我在万能的某宝上找到了它的纸质版,又读了几遍,每次读都有很大的感触,所以我决定拿他作为我的第一篇读书笔记。感悟初次读这本书是我的一个大学同学推荐的,当时我正在大二,那是个时候我感觉到有一丝迷茫,有一丝压力,压力主要在将来就业上,当时我读的不是什么名牌大学,没有什么特别突出的能力,专业课也听得似懂非懂,那个时候总感觉以现在的状态坑定要失业。虽说想要学习点东西,不知道从何学起。那个时候学习的东西太多了,C/C++、Java、HTML、ASP.NET等等,很多东西都是浅尝辄止,一直感觉很无力,。我与几个朋友一起交流的时候,他给我说:“我给你推荐一本书吧,叫《疯狂的程序员》网上有电子版的,这本书是作者根据自身经历写,讲述了主人公从刚进入大学到最后工作再到后期创业的整个故事。里面详细介绍了主角的整个学习过程,主人公从大学一直学习汇编,然后到毕业实习、工作,逐渐过渡到VC++的种种,至此我似乎有了一丝学习的脉络,当时我给自己定下的目标是利用一个寒假好好补一下之前落下的汇编,然后再利用一个学期学习C/C++,当我把汇编学习完了之后我发现C语言里面的指针,数组,结构体,共用体什么的都不再那么神秘,从汇编角度上看只不过是内存的不同摆放方式,采用不同的寻址方式罢了,函数调用,各种传参等等就没有什么难度了,学完汇编再看C语言的种种语法就觉得是那么顺理成章。后来两年中,我基本上是按照这本书中主人公的学习脉络来的,先从汇编到Win32 汇编再到VC++,MFC编程,依照这个顺序,在自学的过程中再也没有遇到过之前那种离了书本就什么都不会的经历,这也给我后面学习带来很大的动力。以前我一直把程序员当做一个理工科的内容,一直认为它只是类似于水利工程师,建筑工程师之类的职业,但是我从这本书中读到一个观点“程序员的双手是魔术师的双手,他将枯燥的代码编程优美的可执行的软件”。原来程序员可以是一个艺术家,是类似于画家的,是可以写出优美的软件,从书中的字里行间,我读到作者作为一个程序员的骄傲,作者那种学习新技术,努力写出优美软件的那种执着。这些都使我对程序员的世界产生了浓厚的兴趣,根据这本书上的相关内容,我注册了一个CSDN,一个看雪的账号,经常在各大程序员论坛潜水,努力希望融入这个圈子,学习程序员文化。可以说这本书带给我关于程序员的启蒙教育,以前一直把程序员当做一个赚钱的行业,当时从那个时候起,我是真正喜欢上了这个职业,喜欢上这种文化。名言警句书中也有许多有意思的想法,时不时爆出一些名言警句什么的,下面我列举出我比较喜欢的一些句子:要么做第一个,要么做最好的一个。什么是鸡肋课?就是每个人都在自己课表的这门课旁边标注一个“可旷”或者“选修”。什么程序优化啊,都抵不上有钱,有钱就是最好的优化。说什么“效率就是金钱”,其实“金钱就是效率”。中国人和外国人很大不同就在于外国人总想热衷于第一时间把自己的新发现公布出来以此向广大人民群众展示自己的水平。中国人往往喜欢把自己的新发现阴在心里,自己偷偷垄断享用。唯恐被第二个人知道。公布出去,相关部门肯定马上解决。所谓好的病毒就是要:“持续时间特别长,波及范围特别广,破坏力特别大。”能进别人系统偷东西,那就是小偷;能进别人系统又不偷东西,那就是黑客。当你不是黑客的时候,总说:“我是个黑客”。当你真正成为黑客的时候,你往往会说:“我不是黑客”程序员是值得尊敬的,程序员的双手是魔术师的双手,他们把枯燥无味的代码变成了丰富多彩的软件……一个人静静的坐在电脑前写大卖的感觉,那是什么感觉?那就是武林高手闭关修炼的感觉。一本好书,就像高级武功秘籍一样,哪怕只从里面领悟个一招半式,功力提升起来都是惊人的,眉超风学的那半生不熟的九阴真经就是证明。所以练武功和写程序一样,不在乎你修炼了几十年还是几百年,也不在乎你少林武当娥眉拜了多少门派,关键是你有没有把一门武艺炼到出神入化的境界。学武艺,最忌讳总想着去追求大而全,你要明白,其实只需要“打狗棍法”这么一招,就足够你掌舵丐帮,受用终生。天下武功出少林,天下语言出汇编提升功力大低有两种方法,一是自己不断写代码,不断完善,不断把自己的代码写好,二是看牛人的代码。牛人的代码实在太高深了,一句看似平凡的语句,也许背后都蕴含着惊天地泣鬼神的智慧。现在你看不出什么端倪,等十年八年之后,你猛然醒悟:啊,原来大牛的代码竟是如此博大精深!对男人来说钱什么都不是,但是你没钱,你就失去了让她了解你的机会。对女人来说漂亮什么都不是,但是你不漂亮,你就失去了让他了解你的机会。人不怕被识破也不怕丢脸,怕就怕被当场识破和当众丢脸。。力的作用是相互的,你打别人有多疼,自己的手就有多疼。与其大家都疼,还不如最开始就不要下手打。每个人都期盼着便宜能光顾到自己,就算没有正儿八经地想,多多少少也偷偷的想过,但是有天便宜真的来了,可要小心了。写程序并不是一辈子都只是写代码。IT这一行是相当广博的,不管你是男的还是女的,不管你技术是初级、中级还是高级,你都能在这行中找到你自己合适的位置。如果你真的用心了,它带给你的会是一生的回报。男人的工资,和女人的年龄差不多。没钱的时候,最忌讳别人追问自己的工资待遇。可男人的工资,又和女人的年龄不一样。女人要是年轻,别人问她年龄,她自然敢大方地回答。男人的工资呢?要是高了,还是怕别人追问。“疯狂的程序员”绝对不是靠狂妄和拼命的程序员,而是能够脚踏实地、持续努力的程序员。一个程序员真正做到了这两点,技术上去之后,唯一能够限制他的只有想像力,到那个时候,才算“疯狂的程序员”,这种程序员啊,才能令竞争对手无比恐惧。技术其实还是我们最需要的东西,以前我们没有过硬的技术,所以疯狂地追求它。现在呢?有了一点技术,便觉得技术不那么重要。如果这样放任下去,等到我们失去技术的那一天,一定会后悔莫及的!最后说点题外话从当时懵懂的菜鸟到现在入行块两年的老菜鸟,目前仍然在学习Windows编程方面的东西,很多人都说现在PC端萎缩,学习PC端的编程没有出路,但是我自己不这么想,编程这个东西与具体的平台无关,与语言无关,编程靠的永远都是基础知识,数学和算法才是王道。但是算法和数学就只看理论是没有办法入门的,必须要实践,而实践的最好方法就是深入一个平台,一门语言不停的学习某个平台某一个语言的相关内容。在学习的途中会涉及到许多算法,操作系统,网络,数据库等等基础部分的知识,有的还可能会涉及到具体的硬件知识。比如Windows平台编程中的进程、线程、内存管理,想要学通这些没有操作系统的相关知识是不可能的,学习网络编程的时候需要网络知识,而数据库则需要数据库相关的知识,而且在Windows中采用的许多框架许多机制一般在其他平台也适用,比如Windows上的回调、消息机制、映射等等相关内容在其他平台其他语言基本上都有,现代操作系统,编程语言都是想通的,基本上是一通百通。因此在学习的过程中不要太纠结于平台和语言。随便选择一个平台,努力深入进去,在编程的同时学习一下基础理论的内容。不要被目前很火的大数据、人工智能云计算,等等东西蒙蔽了头脑,它们说到底也是对数学和算法在具体环境中的应用而已,只要有扎实的基础,想要跳到对应行业,只需要了解对应语言的语法,相应的接口而已。归结起来就一句话:数学和算法是王道。以上都是一个IT菜鸟的肤浅的理解而已,同意就点个赞,不同意也不要喷!!!!
2018年01月07日
21 阅读
0 评论
0 点赞
2018-01-06
Windows数据库编程接口简介
数据库是计算机中一种专门管理数据资源的系统,目前几乎所有软件都需要与数据库打交道(包括操作系统,比如Windows上的注册表其实也是一种数据库),有些软件更是以数据库为核心因此掌握数据库系统的使用方法以及数据库系统编程接口的使用方法是程序员非常重要的基本技能之一。所以我花了一定的时间学习了在Windows平台上使用COM接口的方式操作数据库。这段时间我会将自己学习过程中掌握的知识和其中的一些坑都发布出来,供个人参考,也方便他人学习
2018年01月06日
50 阅读
0 评论
0 点赞
2018-01-06
hexo next主题为博客添加分享功能
今天心血来潮,决定给博客添加分享功能,百度上首先是找到了使用shareSDK的分享功能,最后在实践的过程中发现它添加时步骤比较多,添加完成后效果比较丑(就是一个长条的浅蓝色按钮),而且点击后想要退出分享比较麻烦(它的取消按钮实在太难找了,它在页面最下方的位置,呈现浅灰色,这个设计太反人类了,决定放弃它了)。在next主题的官方的文档中发现它自身集成了百度分享的功能,所以决定采用百度了。
2018年01月06日
31 阅读
0 评论
0 点赞
2018-01-01
2017总结与2018规划
时间如白驹过隙,回想起过去的2017年仿佛就在昨天,元旦做了几天咸鱼,没有能够及时更新自己的年终总结,在此补上回望2017回望2017,在4月份我换了一份工作,之前的工作实在太闲了,我感觉这样不利于自己的进步,于是在3月份的时候正式提出离职,在4月份进入新公司。工作感悟新公司主要是做Web安全的,而我主要负责一款扫描器插件的开发于扫描器本身的维护工作。这份工作经常给我带来惊喜,就比如说sql注入,正常人的思维是输入一个值,然后在数据库中查询,但是sql注入就不是,它会在输入的查询条件中带上sql语句,这与传统的方式不同,它给我一种耳目一新的感觉。我第一次学习到sql注入的原理时是那样的兴奋,感慨于它的不同寻常。同时也对安全从业者产生了一定的崇拜,他们一定是一些思维活跃的人,是一群打破常规的人,这些都是我决定从事安全行业,努力融入安全圈内。这一年收获很多,在这一年中学习了一些常见漏洞的原理,攻击与防御的相关知识,通过阅读公司扫描器的源代码,学习了一些阅读源代码的方法,虽说还没有总结出一整套的方法论,但是也有一些思路。并根据这些方法我找到对应的代码并进行了一些修改。另外,在这一年中学会了一些脚本语言,比如Python、JavaScript。我自己感觉虽然扫描器是使用VC++语言编写的,但是我在这一年中本身使用最多的反而是Python。在刚入职时使用Python开发了扫描器对于ajax部分的支持,使其能够正常爬取到使用JavaScript动态生成的脚本。后来又使用Python开发了大量的漏洞扫描插件。现在又在使用Python开发一款网站监控软件。可以说这一年如果不是自己一直在自学VC的内容,可能现在C的东西都忘干净了^_^由于需要与Web程序打交道,所以一些理论方面的内容必定会涉及到,这一年主要详细了解了http协议,但是主要是在数据包层面上的,比如http的协议头、协议体等等,对于网络底层的东西仍然不是太明白,这也是目前的一个短板。后来为了方便,使用Python发送网络包的时候主要使用的requests库。知道了使用requests库定制协议头、判断响应包等等操作。但是反而对原生的urllib库不太了解。总结这一年我感觉最有用处的项目就是当时我使用Python + webkit写的一个web2.0的爬虫以及现在的一个web监控系统。web监控目前没有完成,所以暂时不提它,这里主要说说web2.0爬虫项目web2.0爬虫参考书籍《白帽子将web扫描》一书,基本代码都是按照书中的思路来的。这个项目使我详细了解了http协议,正则表达式、xpath表达式等等。为了使用webkit,项目主体是一个qt的任务调度部分负责调度由扫描器传过来的需要解析的url,每当有一个url过来的时候,都会触发一个自定义的事件,然后由qt调用对应的槽函数。其实我原本打算使用Python的线程池,来进行调度,但是由于使用的是webkit的Python封装——ghost库,这个库有一个好处就是能够捕捉到所有的网络请求,这样我可以很方便的得到ajax异步加载时请求的URL,从而得到一些额外的url,当时ghost库使用的是全局的app类对象,qt又不允许跨线程访问对象,所以没办法取消了多线程。后来经过我的测试在性能上虽然有一些损失但是损失在能接受的范围内。在解析url时候主要解析下面几种:在一些常规标签中的url,对于这种采用的是常规的xpath表达式出现在文本内容中的链接,或者JavaScript脚本中的链接,这种采用的是正则表达式需要进行异步请求的链接,这种链接主要出现在一些JavaScript注册的事件中。这种链接主要使用ghost库,获取所有网络请求,然后解析其中的url还有就是一些需要进行渲染之后才能出现的链接,对于这种链接,采用的是ghost库中的webkit进行渲染然后解析生成的HTML其余事项我在国庆期间去了一趟深圳,见了一下之前的大学同学,虽然很遗憾,不少人都回去了,但是我见到了当年的室友,以及领我上安全这条路的大牛同学。在于大牛同学的一些交谈中,我发现自己进步的没有想象中那么大,这些都激励着我继续努力不足2017虽然有进步,但是也有许多的不足:生活过于懒散:最大的毛病在于生活过于懒散,没有规律。经常周五熬夜做自己感兴趣的事,一旦这件事做完了或者碰到瓶颈没法解决的时候,后面几天就成了一无是处的咸鱼。手机占据了大量的业余时间,在这一年中,公司很多时候没有什么大事,加班比较少,我虽然回来的早,但是大量的时间用在玩手机上,根据我自己的观察,差不多从7点到8点半的时间很多时候都是在玩手机。而且有时候在学习的时候集中不了精力,时不时会看看手机,这样极大的影响了注意力。缺少锻炼:要说这一年什么收获最大,那应该是我身上的30斤肥肉T_T,从年初的100多斤涨到现在快130斤,在加上自己经常久坐,导致现在有时候稍微活动一下就浑身不舒服,浑身酸痛。18年需要改变这一现状读书太少:这一条与玩手机太多有很大的关系,长时间玩手机,使读书的时间压缩了,有时候200多页的书需要看个把月,总体算下来,今年一年加上在kindle上的书共有6本,明年可能要花更多时间在读书上展望2018生活习惯针对上述出现的问题2018年决定做如下改变:多锻炼:目前计划在3月份房子到期找到新地方后就近找一个健身房办张卡,经常去锻炼身体,并且强迫自己每个星期必须出去走走按时休息:每天按时休息不再分周末和平时,到点了放下手机或者手中的事睡觉,周末白天尽量在8点前起来,保证每天早上出去吃个早餐尝试自己做饭,少点外卖学习计划详细学习网络原理系统学习渗透测试,一些常见漏洞的攻击与防御学习一些逆向的知识学习一些Windows驱动编程的东西看完之前的一套VC高级编程的视频,并针对每个知识点编写相应的代码多写博客,做到每周一篇技术博客,尝试写一些读书笔记、鸡汤、项目总结类的文章将CSDN博客中之前写的VC反汇编系列、VC高级编程系列的内容慢慢转到自己在GitHub的博客上我的博客合理利用周末,周末做到每天玩手机时间不超过2小时,平时不超过半小时2018书单2018年计划读如下书目:1.《白帽子讲Web安全》2.《TCP\IP协议》3.《数学之美》4.《人类简史》5.《未来简史》6.《腾讯传》7.《古龙全集》(利用坐地铁的时间)8.《球状闪电》 最后祝我与所有朋友2018越来越好
2018年01月01日
14 阅读
0 评论
0 点赞
2017-12-19
为 MariaDB 配置远程访问权限
最近在配置MySQL远程连接的时候发现我的MySQL数据库采用的是 MariaDB 引擎,与普通的数据库配置有点不同经过查找资料终于完成了,特此记录方便以后查询MariaDB 与普通的MySQL数据库的一个不同在于它的配置文件不止一个,它将不同的数据放入到不同的配置文件中,之前的/etc/mysql/my.cnf内容如下:从文件中的注释上来看,它主要有这么几个配置文件/etc/mysql/mariadb.cnf 默认配置文件,/etc/mysql/conf.d/*.cnf 设置全局项的文件"/etc/mysql/mariadb.conf.d/*.cnf" 设置与MariaDB相关的信息"~/.my.cnf" 设置该账户对应的信息这也就是为什么我们在my.cnf做相关设置有的时候不起作用(可能在其他配置文件中有相同的项,MySQL最终采用的是另外一个文件中的设置)。根据官方的说法, MariaDB为了提高安全性,默认只监听127.0.0.1中的3306端口并且禁止了远程的TCP链接,我们可以通过下面两步来开启MySQL的远程服务注释掉skip-networking选项来开启远程访问.注释bind-address项,该项表示运行哪些IP地址的机器连接,允许所有远程的机器连接但是配置文件这么多,这两选项究竟在哪呢?这个时候使用grep在/etc/mysql/目录中的所有文件中递归查找,看哪个文件中含有这个字符串我们输入:grep -rn "skip-networking" *,结果如下:十分幸运的是这两项都在同一文件中(我自己的是没有skip-networking项)我们打开文件/etc/mysql/mariadb.conf.d/50-server.cnf,注释掉bind-address项,如下:只有这些仍然不够,我们只是开启了MySQL监听远程连接的选项,接下来需要给对应的MySQL账户分配权限,允许使用该账户远程连接到MySQL输入select User, host from mysql.user;查看用户账号信息:root账户中的host项是localhost表示该账号只能进行本地登录,我们需要修改权限,输入命令:GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;修改权限。%表示针对所有IP,password表示将用这个密码登录root用户,如果想只让某个IP段的主机连接,可以修改为GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.100.%' IDENTIFIED BY 'my-new-password' WITH GRANT OPTION;注意:此时远程连接的密码可能与你在本地登录时的密码不同了,主要看你在IDENTIFIED BY后面给了什么密码具体的请参考GRANT命令最后别忘了FLUSH PRIVILEGES;保存更改。再看看用户信息:这个时候发现相比之前多了一项,它的host项是%,这个时候说明配置成功了,我们可以用该账号进行远程访问了输入service mysql restart重启远程服务器,测试一下:如果这些都做完了,还是不能连接,可以看一下端口是不是被防火墙拦截了参考地址:官方文档
2017年12月19日
68 阅读
2 评论
0 点赞
2017-12-07
向上取整算法
在进行内存分配的时候一般都需要在实际使用内存大小的基础上进行内存对齐,比如一般32位平台进行4字节对齐,而64位平台使用8字节对齐等等。一般采用的算法是先利用公式$$int(\frac{a + b - 1} { b})$$(其中a是实际使用的内存, b是对齐值)然后根据这个值乘以b即可得到对应的对齐值公式推导$ 假设 A = NB +M (M \in \left[0,B-1\right])$$\because\frac{A}{B} = N + \frac{M}{B}$$\because M \in\left[0, B-1\right]$$\therefore \frac{A}{B} \leq \frac{NB +B -1}{B} \leq \frac{A + B -1}{B}$从上面可以得出$\frac{A}{B}$向上取整可能是int($\frac{A+B-1}{B}$)但是具体是否有比它小的整数,仍然不能确定.因此我们根据推导一下这个结果与$\frac{A}{B}$向上取整的结果是否相同$ 假设 A = NB +M (M \in \left[0,B-1\right])$$当M = 0时UP(\frac{A}{B}) = N$$当M \neq 0时,UP(\frac{A}{B}) = N$而针对int($\frac{A+B-1}{B}$)的结果$当M = 0时int(\frac{A+B-1}{B} )=int(\frac{NB+B -1}{B}) = int(N + 1 - \frac{1}{B}) $$\because \frac{1}{B} < 1$$\therefore int(\frac{A+B-1}{B} )$$当 M \neq 0 时int(\frac{A+B-1}{B} ) = int(\frac{NB +M + B -1}{B}) = int(N + 1 + \frac{M-1}{B})$$当M = 1时 int(\frac{A+B-1}{B} ) = int(N + 1 + \frac{M-1}{B}) = N + 1$$当1 < M \leq B-1时 \frac{M -1}{B} < 1$<br/>$\therefore int(\frac{A+B-1}{B} ) = int(N + 1 + \frac{M-1}{B}) = N$从上面的推导来看二者的值完全相同所以可以得出结论$UP(\frac{A}{B}) = int(\frac{A + B - 1}{B})$所以当我们对A字节的内存进行B字节的对齐时可以使用公式$int(\frac{A + B - 1}{B}) \times B $补充其实还有一个算法long(A + B - 1) &~ (B - 1)也可以计算,但是我没有弄清楚它的原理是什么,暂时不管先记住再说^_^
2017年12月07日
18 阅读
0 评论
0 点赞
2017-11-28
python检测404页面
某些网站为了实现友好的用户交互,提供了一种自定义的错误页面,而不是显示一个大大的404 ,比如CSDN上的404提示页面如下:这样虽然提高了用户体验,但是在编写对应POC进行检测的时候如果只根据返回的HTTP头部信息判断,则很可能造成误报,为了能准确检测到404页面,需要从状态码和页面内容两个方面来进行判断。从状态码来判断比较简单。可以直接使用requests库发送http请求,得到响应码即可。从页面内容上进行判断的话,采用的思路是访问web站点上明显不存在的页面,获取页面内容进行保存,然后访问目标页面,将二者进行比较,如果相似度达到某一阈值,则该页面为404页面,否则为正常页面。为了判断两个页面的相似度,采用Python的simhash库,这个库具体实现的算法我不太懂,但是Python的好处就是:不懂无所谓,直接拿来用就行。这里也只是简单的拿来用一下:#-*- encoding:utf-8 -*- # 404 页面识别 from hashes.simhash import simhash import requests class page_404: def __init__(self, domain): #检测站点 self._404_page = [] # 404页面 self._404_url = [] #404 url self._404_path = ["test_404.html", "404_test.html", "helloworld.html", "test.asp?action=modify&newsid=122%20and%201=2%20union%20select%201,2,admin%2bpassword,4,5,6,7%20from%20shopxp_admin"] #404页面路径,用于生成一部分404页面 self._404_code = [200, 301, 302] #当前可能是404页面的http请求的返回值 #自己构造404url,以便收集一些404页面的信息 for path in self._404_path: for path in self._404_path: if domain[-1] == "/": url = domain + path else: url = domain + "/" + path response = requests.get(url) if response.status_code in self._404_code: self.kb_appent(response.content, url) def kb_appent(self, _404_page, _404_url): if _404_page not in self._404_page: self._404_page.append(_404_page) if _404_url not in self._404_url: self._404_url.append(_404_url) def is_similar_page(self, page1, page2): hash1 = simhash(page1) hash2 = simhash(page2) similar = hash1.similarity(hash2) if similar > 0.85: #当前阈值定义为0.85 return True else: return False def is_404(self, url): if url in self._404_url: return True response = requests.get(url) if response.status_code == 404: return True if response.status_code in self._404_code: for page in self._404_page: if self.is_similar_page(response.content, page): self.kb_appent(url, response.content) #如果是404页面,则保存当前的url和页面信息 return True else: return False return False上面的代码中,检测类中主要保存了这样几个信息:_404_page:404页面,用于与其他请求的页面进行相似度判断,以便识别404页面,这里用列表主要为了防止一个站点有多种404页面,这段代码运行时间越长它的准确度越高_404_url:404 页面的url,保存之前判断出页面是404的url,已经判断出来的就不再判断,为了提升效率_404_path:构建不存在页面的url,最后一个是一个sql注入的代码,这里为了识别出那些被防火墙拦截而显示的错误页面_404_code:可能返回404页面的响应码,如果响应码为这些,则需要对页面进行判断类在初始化时需要传入一个域名,根据这个域名来拼接几个不存在的或者会被防火墙拦截的请求并提交这些请求,得到返回信息,将这些信息作为判断的信息进行保存。在判断时首先根据之前保存的404 url信息进行判断,如果当前url是404页面则直接返回,提高效率。然后提交正常的http请求并获取响应信息,如果响应码为404则返回True,否则再状态码是否在_404_code列表中,最后再与之前保存的404页面信息进行比较得到结果。这段代码的测试代码如下:from page_404 import page_404 if __name__ == '__main__': domain = "http://xzylrd.gov.cn" check_404 = page_404(domain) dest_url = "http://xzylrd.gov.cn/TEXTBOX2.ASP?action=modify&newsid=122%20and%201=2%20union%20select%201,2,admin%2bpassword,4,5,6,7%20from%20shopxp_admin" print (check_404.is_404(dest_url))
2017年11月28日
21 阅读
0 评论
0 点赞
2017-11-02
COM学习(四)——COM中的数据类型
上一次说到,COM为了跨语言,有一套完整的规则,只要COM组件按照规则编写,而不同的语言也按照对应的规则调用,那么就可以实现不同语言间相互调用。但是根据那套规则,只能识别接口,并调用没有参数和返回类型的接口,毕竟不同语言里面的基本数据类型不同,可能在VC++中char * 就表示字符串,而在Java或者c#中string是一个对象,二者的内存结构不同,不能简单的进行内存数据类型的强制转化。为了实现数据的正常交互,COM中又定义了一组公共的数据类型。HRESULT类型:在COM中接口的返回值强制定义为该类型,用于表示当前执行的状态是完成或者是出错,这个类型一般在VC中使用,别的语言在调用时根据接口的这个值来确定接下来该如何进行。HRESULT类型的定义如下:typedef _Return_type_success_(return >= 0) long HRESULT;其实它就是一个32位的整数,微软将这个整数分成几个部分,各个部分都有详细的含义,这个值的详细解释在对应的winerror.h中。// // Note: There is a slightly modified layout for HRESULT values below, // after the heading "COM Error Codes". // // Search for "**** Available SYSTEM error codes ****" to find where to // insert new error codes // // Values are 32 bit values laid out as follows: // // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 // +-+-+-+-+-+---------------------+-------------------------------+ // |S|R|C|N|r| Facility | Code | // +-+-+-+-+-+---------------------+-------------------------------+ // // where // // S - Severity - indicates success/fail // // 0 - Success // 1 - Fail (COERROR) // // R - reserved portion of the facility code, corresponds to NT's // second severity bit. // // C - reserved portion of the facility code, corresponds to NT's // C field. // // N - reserved portion of the facility code. Used to indicate a // mapped NT status value. // // r - reserved portion of the facility code. Reserved for internal // use. Used to indicate HRESULT values that are not status // values, but are instead message ids for display strings. // // Facility - is the facility code // // Code - is the facility's status code // // // Define the facility codes //根据上面的注释可以看到,以及我自己查阅相关资料,它里面总共有7个部分,各个部分代表的含义如下:S - 严重性 - 表示成功或失败0 - 成功,1 - 失败R - 设施代码的保留部分,对应于NT的第二严重性位。1 - 严重故障C - 第三方。 此位指定值是第三方定义还是Microsoft定义的。0 - Microsoft-定义,1 - 第三方定义N - 保留部分设施代码。 用于指示映射的NT状态值。X - 保留部分设施代码。 保留供内部使用。 用于指示不是状态值的HRESULT值,而是用于显示字符串的消息标识。Facility - 表示引发错误的系统服务. 示例Facility代码如下所示:2 - 调度(COM调度)3 - 存储 (OLE存储)4 - ITF (COM/OLE 接口管理)7 - (原始 Win32 错误代码)8 - Windows9 - SSPI10 - 控制11 - CERT (客户端或服务器认证)...Code - 设施的状态代码其实这些没有必要知道的很详细,只需要知道里面常用的几个即可:S_OK:成功S_FALSE:失败E_NOINTERFACE:没有接口,一般是由QueryInterface或者CoCreateInterface函数返回,当我们传入的ID不对它找不到对应的接口时返回该值E_OUTOFMEMORY:当内存不足时返回该值。一般在COM的调用者看来,有的时候只要最高位不为0就表示成功,这个时候可能会继续使用,所以在我们自己编写组件的时候要根据具体情况选择返回值,不要错误了就返回S_FALSE,其实我们看它的定义可以知道它是等于1的,最高位为0,仍然是成功的。如果返回S_FALSE可能会造成意想不到的错误,而且还难以调试。BSTRCOM中规定了一种通用的字符串类型BSTR,查看BSTR的定义如下:typedef /* [wire_marshal] */ OLECHAR *BSTR; typedef WCHAR OLECHAR;从上面的定义上不难看出BSTR其实就是一个WCHAR ,也就是一个指向宽字符的指针。COM中使用的是UNICODE字符串,在编写COM程序的时候经常涉及到CString、WCHAR、char等的相互转化,其实本质上就是多字节字符与宽字节字符之间的转化。我们平时在进行char 与WCHAR*之间转化的函数像WideCharToMultiByte和MultiByteToWideChar,以及W2A和A2W等。COM为了方便使用,另外也提供了一组转化函数_com_util::ConvertBSTRToString以及_com_util::ConvertStringToBSTR用在在char*与BSTR之间进行转化。需要注意的是,这组函数返回的字符串是在堆上分配出来的,使用完后需要自己释放。在BSTR类型中,定义了两个函数SysAllocString(),和SysFreeString()用来分配和释放一个BSTR的内存空间。在这总结一下他们之间的相互转化:char*----->BSTR: _com_util::ConvertStringToBSTRWCHAR*---->BSTR:可以直接用 = 进行赋值,也可以使用SysAllocStringBSTR---->WCHAR:一般是直接使用等号即可,但是在WCHAR使用完之前不能释放,所以一般都是赋值给一个CStringBSTR---->char*:_com_util::ConvertBSTRToStringConvert函数是定义在头文件atlutil.h中并且需要引用comsupp.lib文件另外COM封装了一个_bstr_t的类,使用这个类就更加方便了,它封装了与char*之间的相互转化,可以直接使用赋值符号进行相互转化,同时也不用考虑回收内存的问题,它自己会进行内存回收。VARIANT 万能类型现代编程语言一般有强类型的语言和弱类型的语言,强类型的像C/C++、Java这样的,必须在使用前定义变量类型,而弱类型像Python这样的可以直接定义变量而不用管它的类型,甚至可以写出像:i = 0 i = "hello world"这样的代码,而且不同语言中可能同一种类型的变量在内存布局上也可能不一样。解决不同语言之间变量类型的冲突,COM定义了一种万能类型——VARIANT。typedef struct tagVARIANT VARIANT; typedef struct tagVARIANT VARIANTARG; struct tagVARIANT { union { struct __tagVARIANT { VARTYPE vt; WORD wReserved1; WORD wReserved2; WORD wReserved3; union { LONGLONG llVal; LONG lVal; BYTE bVal; SHORT iVal; FLOAT fltVal; DOUBLE dblVal; VARIANT_BOOL boolVal; _VARIANT_BOOL bool; SCODE scode; CY cyVal; DATE date; BSTR bstrVal; IUnknown *punkVal; IDispatch *pdispVal; SAFEARRAY *parray; BYTE *pbVal; SHORT *piVal; LONG *plVal; LONGLONG *pllVal; FLOAT *pfltVal; DOUBLE *pdblVal; VARIANT_BOOL *pboolVal; _VARIANT_BOOL *pbool; SCODE *pscode; CY *pcyVal; DATE *pdate; BSTR *pbstrVal; IUnknown **ppunkVal; IDispatch **ppdispVal; SAFEARRAY **pparray; VARIANT *pvarVal; PVOID byref; CHAR cVal; USHORT uiVal; ULONG ulVal; ULONGLONG ullVal; INT intVal; UINT uintVal; DECIMAL *pdecVal; CHAR *pcVal; USHORT *puiVal; ULONG *pulVal; ULONGLONG *pullVal; INT *pintVal; UINT *puintVal; struct __tagBRECORD { PVOID pvRecord; IRecordInfo *pRecInfo; } __VARIANT_NAME_4; } __VARIANT_NAME_3; } __VARIANT_NAME_2; DECIMAL decVal; } __VARIANT_NAME_1; };从定义上看出,它其实是一个巨大的联合体,将所有C/C++的基本类型都包含进来,甚至包含了像BSTR, 这样的COM中使用的类型。它通过成员vt来表示它当前使用的是哪种类型的变量。vt的类型是一个枚举类型,详细的定义请参见MSDN。为了简化操作,COM中也对它进行了一个封装——_variant_t,该类型可以直接使用任何类型的数据对其进行初始化操作。但是在使用里面的值时还是得判断它的vt成员的值COM中的其他操作最后附上一张COM常用函数表以供参考:
2017年11月02日
14 阅读
0 评论
0 点赞
2017-10-30
COM学习(三)——COM的跨语言
COM是基于二进制的组件模块,从设计之初就以支持所有语言作为它的一个目标,这篇文章主要探讨COM的跨语言部分。idl文件一般COM接口的实现肯定是以某一具体语言来实现的,比如说使用VC++语言,这就造成了一个问题,不同的语言对于接口的定义,各个变量的定义各不相同,如何让使用vc++或者说Java等其他语言定义的接口能被别的语言识别?为了达到这个要求,定义了一种文件格式idl——(Interface Definition Language)接口定义语言,IDL提供一套通用的数据类型,并以这些数据类型来定义更为复杂的数 据类型。一般来说,一个文件有下面几个部分说明接口的定义组件库的定义实现类的定义而各个部分又包括他们的属性定义,以及函数成员的定义属性:属性是在接口定义的上方,使用“[]”符号包裹,一般在属性中使用下面几个关键字:object:标明该部分是一个对象(可以理解为c++中的对象,包括接口和具体的实现类)uuid:标明该部分的GUIDversion:该部分的版本接口定义接口定义采用关键字interface,接口函数定义在一对大括号中,它的定义与类的定义相似,其中函数定义需要修饰函数各个参数的作用,比如使用in 表示它作为输入参数,out表示作为输出参数,retval表示该参数作为返回值,一般在VC++定义的接口中,函数返回值为HRESULT,但是需要返回一个值供外界调用,此时就使用输出参数并加上retval表示它将在其他语言中作为函数的返回值。组件库定义库使用library关键字定义,在定义库的时候,它的属性一般定义GUID和版本信息,而在库中通常定义库中的实现类的相关信息,库中的信息也是写在一对大括号中实现类的定义接口实现类使用关键字coclass,接口类的属性一般定义一个object,一个GUID,然后一般定义实现类不需要向在C++中那样定义它的各个接口,各个数据成员,只需要告知它实现哪些接口即可,也就是说它继承自哪些接口。下面是一个具体的例子:import "unknwn.idl"; [ object, uuid(CF809C44-8306-4200-86A1-0BFD5056999E) ] interface IMyString : IUnknown { HRESULT Init([in] BSTR bstrInit); HRESULT GetLength([out, retval] ULONG *pretLength); HRESULT Find([in] BSTR bstrFind, [out, retval] BSTR* bstrSub); }; [ uuid(ADF50A71-A8DD-4A64-8CCA-FFAEE2EC7ED2), version(1.0) ] library ComDemoLib { importlib("stdole32.tlb"); [ uuid(EBD699BA-A73C-4851-B721-B384411C99F4) ] coclass CMyString { interface IMyString; }; };上面的例子中定义了一个IMyString接口继承自IUnknown接口,函数参数列表中in表示参数为输入参数,out表示它为输出参数,retval表示该参数是函数的返回值。import导入了一个库文件类似于include。而importlib导入一个tlb文件,我们可以将其看成VC++中的#pragma comment导入一个lib库从上面不难看出一个IDL文件至少有3个ID,一个是接口ID,一个是库ID,还有一个就是实现类的ID在VC环境中通过midl命令可以对该文件进行编译,编译会生成下面几个我们在编写实现时会用到的重要文件:一个.h文件:包含各个部分的声明,以及接口的定义一个_i.c文件:包含各个部分的定义,主要是各个GUI的定义需要实现的导出函数一般我们需要在dll文件中导出下面几个全局的导出函数:STDAPI DllRegisterServer(void); STDAPI DllUnregisterServer(void); STDAPI DllGetClassObject(const CLSID & rclsid, const IID & riid, void ** ppv); STDAPI DllCanUnloadNow(void);其中DllRegisterServer用来向注册表中注册模块的相关信息,主要注测在HKEY_CLASSES_ROOT中,主要定义下面几项内容:字符串名称项,该项中包含一个默认值,一般给组件的字符串名称;CLSID子健,一般给实现类的GUID;CurVer子健一般是子健的版本以版本字符串为键的注册表项,该项中主要保存:默认值,当前版本的项目名称;CLSID当前版本库的实现类的GUID在HKEY_CLASSES_ROOT/CLSID子健中注册以实现类GUID字符串为键的注册表项,里面主要包含:默认值,组件字符串名称;InprocServer32,组件所在模块的全路径;ProgID组件名称;TypeLib组件类型库的ID,也就是在定义IDL文件时,定义的实现库的GUID。下面是具体的定义:const TCHAR *g_RegTable[][3] = { { _T("CLSID\\{EBD699BA-A73C-4851-B721-B384411C99F4}"), 0, _T("FirstComLib.MyString")}, //组件ID { _T("CLSID\\{EBD699BA-A73C-4851-B721-B384411C99F4}\\InprocServer32"), 0, (const TCHAR*)-1 }, //组建路径 { _T("CLSID\\{EBD699BA-A73C-4851-B721-B384411C99F4}\\ProgID"), 0, _T("FirstComLib.MyString")}, //组件名称 { _T("CLSID\\{EBD699BA-A73C-4851-B721-B384411C99F4}\\TypeLib"), 0, _T("{ADF50A71-A8DD-4A64-8CCA-FFAEE2EC7ED2}") }, //类型库ID { _T("FirstComLib.MyString"), 0, _T("FirstComLib.MyString") }, //组件的字符串名称 { _T("FirstComLib.MyString\\CLSID"), 0, _T("{EBD699BA-A73C-4851-B721-B384411C99F4}")}, //组件的CLSID { _T("FirstComLib.MyString\\CurVer"), 0, _T("FirstComLib.MyString.1.0") }, //组件版本 { _T("FirstComLib.MyString.1.0"), 0, _T("FirstComLib.MyString") }, //当前版本的项目名称 { _T("FirstComLib.MyString.1.0\\CLSID"), 0, _T("{EBD699BA-A73C-4851-B721-B384411C99F4}")} //当前版本的CLSID };使用上一篇博文的代码,来循环注册这些项即可DllGetClassObject:该函数用来生成对应的工厂类,而工厂类负责产生对应接口的实现类。DllCanUnloadNow:函数用来询问是否可以卸载对应的dll,一般在COM中有两个全局的引用计数,用来记录当前内存中有多少个模块中的类,以及当前有多少个线程在使用它,如果当前没有线程使用或者存在的对象数为0,则可以卸载实现类的定义实现部分的整体结构图如下:由于所有类都派生自IUnknown,所在在这里就不显示这个基类了。每个实现类都对应了一个它具体的类工厂,而项目中CMyString类的类厂的定义如下:class CMyClassFactory : public IClassFactory { public: CMyClassFactory(); ~CMyClassFactory(); STDMETHOD(CreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppvObject); STDMETHOD(LockServer)(BOOL isLock); STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); protected: ULONG m_refs; };STDMETHOD宏展开如下:#define STDMETHOD(method) virtual HRESULT __stdcall method所以上面的代码展开后就变成了:virtual HRESULT __stdcall CreateInstance((IUnknown *pUnkOuter, REFIID riid, void **ppvObject);另外3个派生自IUnknown接口就没什么好说的,主要说说另外两个:CreateInstance:主要用来生成对应的实现类,然后再调用实现类——CMyString的QueryInterface函数生成对应的接口LockServer:当前是否被锁住:如果传入的值为TRUE,则表示被锁住,对应的锁计数器+1, 否则 -1至于CMyString类的代码与之前的大同小异,也就没什么说的。其他语言想要调用,以该项目为例,一般会经历下面几个步骤:调用对应语言提供的产生接口的函数,该函数参数一般是传入一个组件的字符串名称。如果要引用该项目中的组件则会传入FirstComLib.MyString在注册表的HKEY_CLASSES_ROOT\组件字符串名\CLSID(比如HKEY_CLASSES_ROOT\FirstComLib.MyString\CLSID)中找到对应的CLSID值在HKEY_CLASSES_ROOT\CLSID\对应ID\InprocServer32(CLSID\{EBD699BA-A73C-4851-B721-B384411C99F4}\InprocServer32)位置处找到对应模块的路径加载该模块根据IDL文件告知其他语言里面存在的接口,由语言调用对应的创建接口的函数创建接口调用模块的导出函数DllGetClassObject将查询到的CLSID作为第一个参数,并将接口ID作为第二个参数传入,得到一个接口6.后面根据idl文件中的定义,直接调用接口中提供的函数真实ATLCOM项目的解析最后来看看一个正式的ATLCOM项目里面的内容,来复习前面的内容,首先通过VC创建一个ATLCOM的dll项目在项目上右键-->New Atl Object,输入接口名称,IDE会根据名称生成一个对应的接口,还是以MyString接口为例,完成这一步后,整个项目的类结构如下:这些全局函数的作用与之前的相同,它里面多了一个_Module的全局对象,该对象类似于MFC中的CWinApp类,它用来表示整个项目的实例,里面封装了对于引用计数的管理,以及对项目中各个接口注册信息的管理,所以看DllRegisterServer等函数就会发现它们里面其实很简单,大部分的工作都由_Module对象完成。整个IDL文件的定义如下:import "oaidl.idl"; import "ocidl.idl"; [ object, uuid(E3BD0C14-4D0C-48F2-8702-9F8DBC96E154), dual, helpstring("IMyString Interface"), pointer_default(unique) ] interface IMyString : IDispatch { }; [ uuid(A61AC54A-1B3D-4D8E-A679-00A89E2CBE93), version(1.0), helpstring("FirstAtlCom 1.0 Type Library") ] library FIRSTATLCOMLib { importlib("stdole32.tlb"); importlib("stdole2.tlb"); [ uuid(11CBC0BE-B2B7-4B5C-A186-3C30C08A7736), helpstring("MyString Class") ] coclass MyString { [default] interface IMyString; }; };里面的内容与上一次的内容相差无几,多了一个helpstring属性,该属性用于产生帮助信息,当使用者在调用接口函数时IDE会将此提示信息显示给调用者。由于有系统框架给我们做的大量的工作,我们再也不用关心像引用计数的问题,只需要将精力集中在编写接口的实现上,减少了不必要的工作量。至此从结构上说明了为了实现跨语言COM组件内部做了哪些工作,当然只有这些工作是肯定不够的,后面会继续说明它所做的另一块工作——提供的一堆通用的变量类型。
2017年10月30日
40 阅读
0 评论
0 点赞
1
...
29
30
31
...
40