Category: doc

01

UML


1.建模
1.1 为什么要建模
建立大厦和建立狗窝的区别是建设狗窝不需要设计。要生产合格的软件就要有一套关于体系结构、过程和工具的规范。
建模的定义:建模是对现实的简化。
建模的目标:
1)模型帮助我们按照实际情况或按照我们所需要的样式对系统进行可视化。
2)模型允许我们详细说明系统的结构和行为。
3)模型给出一个知道我们构造系统的模板。
4)模型对我们的决策进行文档化。
建模就是把复杂的系统变成小的系统,采用“各个击破”的原则逐一解决。
1.2 建模原理
1)选择创建什么模型很重要,模型要反映你难于处理的开发问题。
2)模型要在不同的精度级别上来表示。你可以根据观察的角色和观察的原因来选择精度。
3)建造模型要和现实相连。
4)重要的系统需要用一组独立的模型去处理。在面向对象的软件体系中,为了理解系统的体系结构,你需要几个互补和连锁的视图:用例图、设计视图、进程视图、实现视图和实施视图。
1.3 面向对象的建模
面向算法的建模在需求发生变化或者系统增长后就变得难以维护。
面向对象的建模把对象和类作为其主要构造块。例如,在三层结构中,我们可以在用户接口层、中间层和数据库层中找到你想要的对象。
2 UML介绍
2.1 概述
UML可以对软件密集型系统的制品进行可视化、详述、构造和文档化。最好把它用于以用况(用例)为驱动、以体系结构为中心、跌代及增量的过程中。
UML是一种语言,它是一种可视化的语言,它是一组图形符号。它可用于详细描述。它又是一种构造语言,可以直接生成代码。用Rational XDE就可以实现从UML到C#,或者从C#到UML的双向工程。
2.2 UML的概念模型
学习建模的三个要素:UML的基本构造块、这些构造块放在一起的规则、一些运用于整个UML的公共机制。
UML中由一些四种事物
1)结构事物 --- 、接口、协作(它是一个交互,它是由一组共同工作以提供某协作行为的角色和其它元素构成的一个群体。)、用例、主动类(至少拥有一个进程或者线程,其元素的行为可以和其它元素的行为并发)、构件(如COM+和Java Bean)、节点。
2)行为事物 --- 交互、状态机(描述了一个对象或者一个交互在生命期内响应事件所经历的状态序列)。
3)分组事物 --- 包
4)注释事物 --- 注解
UML中的四种关系
1)依赖 --- 两个事物间的语义关系
2)关联 --- 是一种结构关系,如聚合
3)泛化 --- 一般/特殊关系
4)实现 --- 用在两种地方:接口和实现他们之间的类和构件之间;用例和实现他们的协作之间。
UML中的图
1)类图 --- 系统的静态状态图,包含主动类的类图给除系统的静态进程视图。
2)对象图
3)用例图
4)顺序图
5)协作图
6)状态图
7)活动图 --- 强调对象间的控制流程
8)构件图
9)实施图
2.3 体系结构
我们用5个互联的视图来描述软件密集型系统的体系结构:
1)系统的用例图
2)系统的设计视图 --- 静态方面由类图和对象图描述,动态方面由交互图、状态图和活动图描述。
3)系统的进程视图 --- 包含了形成系统并发和同步机制的线程和进程。
4)系统的实现视图 --- 主要针对系统发布的配置管理。
5)系统的实施视图
2.4 软件开发生命周期
用况驱动
以体系结构为中心
跌代过程 --- 涉及到一连串可执行发布的管理。
软件开发生命周期的四个阶段:
初始
细化
构造
移交

3 Hello World
4 类
4.3.1 对系统的词汇建模
需要做如下工作:
1)识别用户用于描述问题或解决问题的事物。
2)对于每个抽象,识别一个职责集。
3)提供为实现每个类的职责所需的属性和操作。
4.3.2 对系统中职责的分布建模
抽象出来的类要适中,不要过大过小。
需要如下工作:
1) 识别一组为了完成某些行为而紧密协同工作的类。
2) 对上面的每一个类识别出一组职责。
3) 从整体上观察这些类,过大的分解,过小的合并。
4) 考虑相映的协作方式,重新分配职责。
5 关系
面向对象建模中三种最重要的关系:
依赖 --- 使用关系
泛化 --- 一般/特殊关系
关联 --- 结构关系
当你开始建模是,特别是解决这些对象的动态协作时,你还会遇到两种其它的关系:链(可能发送消息的对象间的实例)和转换(状态机中不同状态的连接)
对简单依赖建模 ---(如一个类作为另一个类的参数) 依赖从操作的类指向当作参数的类。
对单继承建模
对结构关系建模
6 公共机制
四个公共机制可以使UML简化:详述、修饰、公共划分和扩展
构造型、标记值和约束使UML提供的用以增加新的构造块、创建新的特性以及描述新的语义的机制。
7 图
有5种最重要的互补视图:用例视图、设计视图、进程视图、实现视图和实施视图
每一种视图包含结构建模(静态)和行为建模(动态)
建图的两种方法:正向工程和逆向工程
一些术语:
系统:由子系统组成; 子系统:由元素组成; 模型:对现实的简化; 视图:对系统模型的组织和结构的投影,注重于系统的一个方面。
结构图:类图、对象图、构件图、实施图。
行为图: 用况图、顺序图、协作图、状态图、活动图。
顺序图和协作图统称交互图。顺序图强调消息的时间次序,协作图强调收发消息的对象的结构组织。
活动图强调对象之间的控制流。
如何选择视图来建模?
1)视图能够表达系统的体系结构,能够暴露项目的技术风险。
2)决定用哪些制品来捕获视图的基本细节。
3)作为你的过程策略的一部分,决定把那种视图至于某种形式或者半形式的控制之下。
4)保留废弃的视图。
两种系统建模的方法:
1)针对同一模型,用不同层次上的细节描述图。
2)在不同的抽象层次上,从一个模型跟踪到另一个模型的方法建模。
8 类图
类图包括如下内容:

接口
协作
依赖、泛化和关联关系。
对系统的静态设计视图建模时使用类图的3种方式:
1)对系统的词汇建模
2)对简单协作建模 --- 协作提供的一些合作行为强于其所有元素行为之和。
3)对逻辑数据库模式建模
9 高级类
在UML中更一般的构造块是类元,类元包括:类、接口、数据类型、信号、构件、节点、用况和子系统。他是描述结构特性和行为特性的机制。

转自:http://.csdn.net/binjuny/archive/2007/07/05/1679193.aspx

0

PHP6 features


去年在巴黎举行的PHP开发者大会中,6开发的消息开始流传开来,于PHP大会讨论的PHP6,将有很大幅度的变化,但这只是草案阶段,并不代表所有会议的机率都会随着PHP6的发布而包含记录中所有的变更也就是说,在发布PHP6之前,还是会有异动的情形,但是可以确定的是下面所列的数项变化,将会随着PHP6一同面世(当然不是百分百乐,)赶快来看看这些新特性吧

1.支持Unicode
支持Unicode是有其必然,虽然Unicode占用较多的空间,但Unicode带来的便利性,远超过占用空间的缺点,尤其在国际化的今天,硬件设备越来越强大,网速也大幅度的提升,这么一点小小的缺点是可以忽略的。另外一点,PHP也可以在.ini文件中设定是否开启支持Unicode,决定权在你自己,这是一个不错的点子,关掉Unicode的支持,PHP的性能并不会有大幅度的提升,主要的影响在于需要引用字符串的函数。

2.Register Globals 将被移除
这是一个重要的决定,说多新进的PHP开发者会觉得Register Globals满方便的,但是却忽略了Register Globals会带来程序上安全性的隐患,大多数的主机上此项功能是关闭的,印象中从PHP4.3.x版开始时,此项默认设置值即是关闭状态,PHP6正式移除Register Globals也代表着如果程序是由PHP3时代的产物,将完全无法使用,除了改写一途外,别无他法。相信现在的PHP世界里,仍使用PHP3时代所产生的程序应该是少之又少。

3.Magic Quotes 将消失
Magic Quotes主要是自动转义需要转义的字符,此项功能移除叶符合大多数PHP开发者的心声。

4.Safe Mode 取消
老实说,这个模式不知道哪里不好,取消就取消吧,反正也用不到

5.’var’ 别名为 ‘public’
在类中的var声明变成public的别名,相信是为了兼容PHP5而作的决定,PHP6现在也可以称作为OO语言了。

6.通过引用返回将出错
现在透过引用返回编译器将会报错 例如$a =& new b()、function &c(),OO语言默认就是引用,所以不需要再使用&了。

7.zend.ze1 compatbility mode 将被移去
Zend.ze1相容模式将被移去,PHP5是为兼容旧有PHP4,所以在.ini中可选择是否开启相容模式,原因在于PHP5使用的是第二代解析引擎,但是相容模式并不是百分之百能解析PHP4语法,所以旧时代的产物,移除。

8.Freetype 1 and GD 1 support 将不见
这两个是很久的Libs,所以不再支持,GD1早已被现在的GD2取代了。

9.dl() 被移到 SAPI 中
dl()主要是让设计师加载extension Libs,现在被移到 SAPI 中

10.Register Long Array 去除
从PHP5起默认是关闭,再PHP6中正式移除。

11.一些Extension的变更
例如 XMLReader 和 XMLWriter 将不再是以Extension的方式出现,他们将被移入到PHP的核心之中,并且默认是开启,ereg extension将被放入PECL,代表着它将被移出PHP核心,这也是为了让路给新的正则表达式extension,此外,Fileinfo extension 也将被导入PHP的核心之中。

12.APC将被导入核心
这是一个提高PHP性能的功能,现在它将被放入PHP核心中,并且可以选择是否启用APC

13.告别ASP风格的起始标签
原来是为了取悦ASP开发者转向使用PHP,现今已经不再需要这种做法了,

最后,别期望PHP6的性能可以全面超过PHP5,有可能的是PHP6的执行效率会比PHP5还要来的慢的,但是可以预期的是,PHP开发小组将会努力的完善PHP5,超越PHP5。

那么,对PHP6有兴趣的朋友现在可以到PHP官方网站上下载,试试这些功能是否真的已经
在PHP6中体现出来了,下载地址http://snaps.php.net/

0

[收藏] Asian NTP Server pool


Philippines — ph...org (1)
Malaysia — my.pool.ntp.org (4)
Turkey — tr.pool.ntp.org (1)
Singapore — sg.pool.ntp.org (2)
India — in.pool.ntp.org (1)
Hong Kong — hk.pool.ntp.org (1)
United Arab Emirates — ae.pool.ntp.org (0)
Japan — jp.pool.ntp.org (6)
Bangladesh — bd.pool.ntp.org (0)
Israel — il.pool.ntp.org (3)
Korea — kr.pool.ntp.org (4)
Thailand — th.pool.ntp.org (1)
Iran — ir.pool.ntp.org (0)
Taiwan — tw.pool.ntp.org (15)
China — cn.pool.ntp.org (6)
Indonesia — id.pool.ntp.org (3)

0

[超长篇] Inject Your Code to a Portable Executable File


转至: http://www.codeguru.com/cpp/w-p/system/misc/article.php/c11393

Downloads

  • pemaker1.zip
  • pemaker2.zip
  • pemaker3.zip
  • pemaker4.zip
  • pemaker5.zip
  • peviewer.zip
  • test1.zip
  • Windows NT 3.51 (I mean, Win3.1, Win95, Win98 were not perfect OSs). The MS-DOS data causes that your executable file to have the performance inside MS-DOS and the MS-DOS Stub program lets it display: "This program can not be run in MS-DOS mode" or "This program can be run only in mode", or some things like these comments when you try to run a Windows EXE file inside MS-DOS 6.0, where there is no footstep of Windows. Thus, this data is reserved for the code to indicate these comments in the MS-DOS operating system. The most interesting part of the MS-DOS data is "MZ"! Can you believe, it refers to the name of "Mark Zbikowski", one of the first Microsoft programmers?

    0 Preface

    You might demand to comprehend the ways a virus program injects its procedure into the interior of a portable executable file and corrupts it, or you are interested in implementing a packer or a protector to encrypt the data of your portable executable (PE) file. This article is committed to represent a brief discussion to realize the performance that is accomplished by EXE tools or some kinds of mal-ware.

    You can employ this article’s source code to create your custom EXE builder. It could be used to make an EXE protector in the right way, or with the wrong intention, to spread a virus. However, my purpose of writing this article has been the first application, so I will not be responsible for the immoral usage of these methods.

    1 Prerequisites

    There are no specific mandatory prerequisites to follow the topics in this article. If you are familiar with a debugger and also the portable file format, I suggest you to drop to Sections 2 and 3; the whole of these sections has been made for people who don’t have any knowledge regarding the EXE file format or debuggers.

    2 Portable Executable File Format

    The Portable Executable file format was defined to provide the best way for the Windows Operating System to execute code and also to store the essential data that is needed to run a program—for example constant data, variable data, import library links, and resource data. It consists of MS-DOS file information, Windows NT file information, Section Headers, and Section images, as shown in Table 1.

    2.1 The MS-DOS data

    These data let you remember the first days of developing the Windows Operating System. You were at the beginning of a way to achieve a complete Operating System such as

    To me, only the offset of the PE signature in the MS-DOS data is important, so I can use it to find the position of the Windows NT data. I just recommend that you take a look at Table 1, and then observe the structure of IMAGE_DOS_HEADER in the <winnt.h> header in the <Microsoft Visual Studio .net path>\VC7\PlatformSDK\include\ folder or the <Microsoft Visual Studio 6.0 path>\VC98\include\ folder. I do not know why the Microsoft team has forgotten to provide some comment about this structure in the MSDN library!

    typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header "MZ"    WORD   e_magic;                // Magic number    WORD   e_cblp;                 // Bytes on last page of file    WORD   e_cp;                   // Pages in file    WORD   e_crlc;                 // Relocations    WORD   e_cparhdr;              // Size of header in                                   // paragraphs    WORD   e_minalloc;             // Minimum extra paragraphs                                   // needed    WORD   e_maxalloc;             // Maximum extra paragraphs                                   // needed    WORD   e_ss;                   // Initial (relative) SS                                   // value    WORD   e_sp;                   // Initial SP value    WORD   e_csum;                 // Checksum    WORD   e_ip;                   // Initial IP value    WORD   e_cs;                   // Initial (relative) CS                                   // value    WORD   e_lfarlc;               // File address of relocation                                   // table    WORD   e_ovno;                 // Overlay number    WORD   e_res[4];               // Reserved words    WORD   e_oemid;                // OEM identifier                                   // (for e_oeminfo)    WORD   e_oeminfo;              // OEM information;                                   // e_oemid specific    WORD   e_res2[10];             // Reserved words    LONG   e_lfanew;               // File address of the new                                   // exe header  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

    e_lfanew is the offset that refers to the position of the Windows NT data. I have provided a program to obtain the header information from an EXE file and to display it to you. To use the program, just try:

    PE Viewer


    (Full Size Image)


    (Full Size Image)

    This sample is useful for the whole of this article.

    Table 1: Portable Executable file format structure

    MS-DOS
    information
    IMAGE_DOS_
    HEADER
    DOS EXE Signature
    00000000  ASCII "MZ"00000002  DW 009000000004  DW 000300000006  DW 000000000008  DW 00040000000A  DW 00000000000C  DW FFFF0000000E  DW 000000000010  DW 00B800000012  DW 000000000014  DW 000000000016  DW 000000000018  DW 00400000001A  DW 00000000001C  DB 00b&b&0000003B  DB 000000003C  DD 000000F0
    DOS_PartPag
    DOS_PageCnt
    DOS_ReloCnt
    DOS_HdrSize
    DOS_MinMem
    DOS_MaxMem
    DOS_ReloSS
    DOS_ExeSP
    DOS_ChkSum
    DOS_ExeIPP
    DOS_ReloCS
    DOS_TablOff
    DOS_Overlay
    b&
    Reserved words
    b&
    Offset to PE signature
    MS-DOS Stub
    Program
    00000040  ..B:..B4.C!B8\LC!This program canno00000060  t be run in DOS mode....$.......
    Windows NT
    information

    IMAGE_
    NT_HEADERS

    Signature PE signature (PE)
    000000F0  ASCII "PE"
    IMAGE_
    FILE_HEADER
    Machine
    000000F4  DW 014C000000F6  DW 0003000000F8  DD 3B7D8410000000FC  DD 0000000000000100  DD 0000000000000104  DW 00E000000106  DW 010F
    NumberOfSections
    TimeDateStamp
    PointerToSymbolTable
    NumberOfSymbols
    SizeOfOptionalHeader
    Characteristics
    IMAGE_
    OPTIONAL_
    HEADER32
    MagicNumber
    00000108  DW 010B0000010A  DB 070000010B  DB 000000010C  DD 0001280000000110  DD 00009C0000000114  DD 0000000000000118  DD 000124750000011C  DD 0000100000000120  DD 0001400000000124  DD 0100000000000128  DD 000010000000012C  DD 0000020000000130  DW 000500000132  DW 000100000134  DW 000500000136  DW 000100000138  DW 00040000013A  DW 00000000013C  DD 0000000000000140  DD 0001F00000000144  DD 0000040000000148  DD 0001D7FC0000014C  DW 00020000014E  DW 800000000150  DD 0004000000000154  DD 0000100000000158  DD 001000000000015C  DD 0000100000000160  DD 0000000000000164  DD 00000010
    MajorLinkerVersion
    MinorLinkerVersion
    SizeOfCode
    SizeOfInitializedData
    SizeOfUninitializedData
    AddressOfEntryPoint
    BaseOfCode
    BaseOfData
    ImageBase
    SectionAlignment
    FileAlignment
    MajorOSVersion
    MinorOSVersion
    MajorImageVersion
    MinorImageVersion
    MajorSubsystemVersion
    MinorSubsystemVersion
    Reserved
    SizeOfImage
    SizeOfHeaders
    CheckSum
    Subsystem
    DLLCharacteristics
    SizeOfStackReserve
    SizeOfStackCommit
    SizeOfHeapReserve
    SizeOfHeapCommit
    LoaderFlags
    NumberOfRvaAndSizes
    IMAGE_
    DATA_DIRECTORY[16]
    Export Table
    Import Table
    Resource Table
    Exception Table
    Certificate File
    Relocation Table
    Data
    Architecture Data
    Global Ptr
    TLS Table
    Load Config Table
    Bound Import Table
    Import Address Table
    Delay Import Descriptor
    COM+ Runtime Header
    Reserved
    Sections
    information
    IMAGE_
    SECTION_
    HEADER[0]
    Name[8]
    000001E8  ASCII".text"000001F0  DD 000126B0000001F4  DD 00001000000001F8  DD 00012800000001FC  DD 0000040000000200  DD 0000000000000204  DD 0000000000000208  DW 00000000020A  DW 00000000020C  DD 60000020    CODE|EXECUTE|READ
    VirtualSize
    VirtualAddress
    SizeOfRawData
    PointerToRawData
    PointerToRelocations
    PointerToLineNumbers
    NumberOfRelocations
    NumberOfLineNumbers
    Characteristics
    b&
    b&
    b&
    IMAGE_
    SECTION_
    HEADER[n]
    00000210  ASCII".data"; SECTION00000218  DD 0000101C ; VirtualSize = 0x101C0000021C  DD 00014000 ; VirtualAddress = 0x1400000000220  DD 00000A00 ; SizeOfRawData = 0xA0000000224  DD 00012C00 ; PointerToRawData = 0x12C0000000228  DD 00000000 ; PointerToRelocations = 0x00000022C  DD 00000000 ; PointerToLineNumbers = 0x000000230  DW 0000     ; NumberOfRelocations = 0x000000232  DW 0000     ; NumberOfLineNumbers = 0x000000234  DD C0000040 ; Characteristics =                        INITIALIZED_DATA|READ|WRITE00000238  ASCII".rsrc"; SECTION00000240  DD 00008960 ; VirtualSize = 0x896000000244  DD 00016000 ; VirtualAddress = 0x1600000000248  DD 00008A00 ; SizeOfRawData = 0x8A000000024C  DD 00013600 ; PointerToRawData = 0x1360000000250  DD 00000000 ; PointerToRelocations = 0x000000254  DD 00000000 ; PointerToLineNumbers = 0x000000258  DW 0000     ; NumberOfRelocations = 0x00000025A  DW 0000     ; NumberOfLineNumbers = 0x00000025C  DD 40000040 ; Characteristics =                        INITIALIZED_DATA|READ
    SECTION[0]
    00000400  EA 22 DD 77 D7 23 DD 77  C*"C.wC.#C.w00000408  9A 18 DD 77 00 00 00 00  E!.C.w....00000410  2E 1E C7 77 83 1D C7 77  ..C.wF..C.w00000418  FF 1E C7 77 00 00 00 00  C?.C.w....00000420  93 9F E7 77 D8 05 E8 77  b.E8C'wC..C(w00000428  FD A5 E7 77 AD A9 E9 77  C=B%C'w&shy;B)C)w00000430  A3 36 E7 77 03 38 E7 77  B#6C'w.8C'w00000438  41 E3 E6 77 60 8D E7 77  AC#C&w`BC'w00000440  E6 1B E6 77 2B 2A E7 77  C&.C&w+*C'w00000448  7A 17 E6 77 79 C8 E6 77  z.C&wyC.C&w00000450  14 1B E7 77 C1 30 E7 77  ..C'wC.0C'wb&
    b&
    b&
    b&
    SECTION[n]
    b&0001BF00  63 00 2E 00 63 00 68 00  c...c.h.0001BF08  6D 00 0A 00 43 00 61 00  m...C.a.0001BF10  6C 00 63 00 75 00 6C 00  l.c.u.l.0001BF18  61 00 74 00 6F 00 72 00  a.t.o.r.0001BF20  11 00 4E 00 6F 00 74 00  ..N.o.t.0001BF28  20 00 45 00 6E 00 6F 00   .E.n.o.0001BF30  75 00 67 00 68 00 20 00  u.g.h. .0001BF38  4D 00 65 00 6D 00 6F 00  M.e.m.o.0001BF40  72 00 79 00 00 00 00 00  r.y.....0001BF48  00 00 00 00 00 00 00 00  ........0001BF50  00 00 00 00 00 00 00 00  ........0001BF58  00 00 00 00 00 00 00 00  ........0001BF60  00 00 00 00 00 00 00 00  ........0001BF68  00 00 00 00 00 00 00 00  ........0001BF70  00 00 00 00 00 00 00 00  ........0001BF78  00 00 00 00 00 00 00 00  ........

    2.2 The Windows NT data

    As mentioned in the preceding section, e_lfanew storage in the MS-DOS data structure refers to the location of the Windows NT information. Hence, if you assume that the pMem pointer relates the start point of the memory space for a selected portable executable file, you can retrieve the MS-DOS header and also the Windows NT headers by the following lines, which you also can perceive in the PE viewer sample (pelib.cpp, PEStructure::OpenFileName()):

    IMAGE_DOS_HEADER        image_dos_header;IMAGE_NT_HEADERS        image_nt_headers;PCHAR pMem;b&memcpy(&image_dos_header, pMem,       sizeof(IMAGE_DOS_HEADER));memcpy(&image_nt_headers,       pMem+image_dos_header.e_lfanew,       sizeof(IMAGE_NT_HEADERS));

    IMAGE_NT_HEADERS structure definition. It makes it possible to grasp what the image NT header maintains to execute a code inside the Windows NT OS. Now, you are conversant with the Windows NT structure; it consists of the "PE" Signature, the File Header, and the Optional Header. Do not forget to take a glimpse at their comments in the MSDN Library and in Table 1.

    It seems to be very simple, the retrieval of the headers information. I recommend inspecting the MSDN library regarding the

    One the whole, I consider merely, in most circumstances, the following cells of the IMAGE_NT_HEADERS structure:

    FileHeader->NumberOfSectionsOptionalHeader->AddressOfEntryPointOptionalHeader->ImageBaseOptionalHeader->SectionAlignmentOptionalHeader->FileAlignmentOptionalHeader->SizeOfImageOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]              ->VirtualAddressOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]              ->Size

    You can observe the main purpose of these values clearly, and their role when the internal virtual memory space allocated for an EXE file by the Windows task manager if you pay attention to their explanations in MSDN library, so I am not going to repeat the MSDN annotations here.

    I should make a brief comment regarding the PE data directories, or OptionalHeader-> DataDirectory[], because I think there are a few aspects of interest concerning them. When you come to survey the Optional header through the Windows NT information, you will find that there are 16 directories at the end of the Optional Header, where you can find the consecutive directories, including their Relative Virtual Address and Size. I just mention here the notes from <winnt.h> to clarify these information:

    // Export Directory#define IMAGE_DIRECTORY_ENTRY_EXPORT          0// Import Directory#define IMAGE_DIRECTORY_ENTRY_IMPORT          1// Resource Directory#define IMAGE_DIRECTORY_ENTRY_RESOURCE        2// Exception Directory#define IMAGE_DIRECTORY_ENTRY_EXCEPTION       3// Security Directory#define IMAGE_DIRECTORY_ENTRY_SECURITY        4// Base Relocation Table#define IMAGE_DIRECTORY_ENTRY_BASERELOC       5// Debug Directory#define IMAGE_DIRECTORY_ENTRY_DEBUG           6// Architecture Specific Data#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE    7// RVA of GP#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR       8// TLS Directory#define IMAGE_DIRECTORY_ENTRY_TLS             9// Load Configuration Directory#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10// Bound Import Directory in headers#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11// Import Address Table#define IMAGE_DIRECTORY_ENTRY_IAT            12// Delay Load Import Descriptors#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13// COM Runtime descriptor#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14

    The last one (15) was reserved for use in the future; I have not yet seen any purpose for it, even in PE64.

    For instance, if you want to perceive the relative virtual address (RVA) and the size of the resource data, it is enough to retrieve them by:

    DWORD dwRVA  = image_nt_headers.OptionalHeader->   DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]->VirtualAddress;DWORD dwSize = image_nt_headers.OptionalHeader->   DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]->Size;

    To comprehend more regarding the significance of data directories, I forward you to Section 3.4.3 of the Microsoft Portable Executable and the Common Object File Format Specification document by Microsoft, and furthermore Section 6 of this document, where you discern the various types of sections and their applications. You will see the section’s advantage subsequently.

    2.3 The Section Headers and Sections

    You currently observe how the portable executable files declare the location and the size of a section on a disk storage file and inside the virtual memory space allocated for the program with IMAGE_NT_HEADERS-> OptionalHeader->SizeOfImage by the Windows task manager, as well the characteristics to demonstrate the type of the section. To better understand the Section header as my previous declaration, I suggest having a brief look at the IMAGE_SECTION_HEADER structure definition in the MSDN library. For an EXE packer developer, VirtualSize, VirtualAddress, SizeOfRawData, PointerToRawData, and Characteristics cells have significant rules. When developing an EXE packer, you should be clever enough to play with them. There are somet hings to note when you modify them; you should take care to align the VirtualSize and VirtualAddress according to OptionalHeader->SectionAlignment, as well as SizeOfRawData and PointerToRawData in line with OptionalHeader->FileAlignment. Otherwise, you will corrupt your target EXE file and it will never run. Regarding Characteristics, I pay attention mostly to establish a section by IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA, I prefer that my new section has the ability to initialize such data during the running process, such as import table; besides, I need it to be able to modify itself by the loader with my settings in the section characteristics to read- and writeable.

    Moreover, you should pay attention to the section names; you can know the purpose of each section by its name. I will just forward you to Section 6 of the Microsoft Portable Executable and the Common Object File Format Specification documents. I believe it represents the totality of sections by their names; this is also included in Table 2.

    Table 2: Section names

    ".text" Code Section
    "CODE" Code Section of file linked by Borland Delphi or Borland Pascal
    ".data" Data Section
    "DATA" Data Section of file linked by Borland Delphi or Borland Pascal
    ".rdata" Section for Constant Data
    ".idata" Import Table
    ".edata" Export Table
    ".tls" TLS Table
    ".reloc" Relocation Information
    ".rsrc" Resource Information

    To comprehend the section headers and also the sections, you can run the sample PE viewer. With this PE viewer, you can realize only the application of the section headers in a file image, so to observe the main significance in the Virtual Memory, you should try to load a PE file by a debugger. The next section represents the main idea of using the virtual address and size in the virtual memory by using a debugger. The last note is about IMAGE_NT_HEADERS-> FileHeader->NumberOfSections, that provides a number of sections in a PE file. Do not forget to adjust it whenever you remove or add some sections to a PE file. I am talking about section injection!

    3 Debugger, Disassembler and some Useful Tools

    In this part, you will become familiar with the necessary and essential equipment to develop your PE tools.

    3.1 Debuggers

    The first essential prerequisite to become a PE tools developer is to have enough experience with bug tracer tools. Furthermore, you should know most of the assembly instructions. To me, the Intel documents are the best references. You can obtain them from the Intel site for IA-32, and on top of that IA-64; the future belongs to IA-64 CPUs, Windows XP 64-bit, and also PE64!

    To trace a PE file, SoftICE by Compuware Corporation, I knew it also as named NuMega when I was at high school, is the best debugger in the world. It implements process tracing by using the kernel mode method debugging without applying Windows debugging application programming interface (API) functions. In addition, I will introduce one perfect debugger in user mode level. It utilizes the Windows debugging API to trace a PE file and also attaches itself to an active process. These API functions have been provided by Microsoft teams, inside the Windows Kernel32 library, to trace a specific process, by using Microsoft tools, or perhaps, to make your own debugger! Some of those API functions inlude:

    3.1.1 SoftICE

    It was in 1987; Frank Grossman and Jim Moskun decided to establish a company called NuMega Technologies in Nashua, NH, to develop some equipment to trace and test the reliability of Microsoft Windows software programs. Now, it is a part of Compuware Corporation and its product has participated to accelerate the reliability in Windows software, and additionally in Windows driver developments. Currently, everyone knows the Compuware DriverStudio that is used to establish an environment for implementing the elaboration of a kernel driver or a system file by aiding the Windows Driver Development Kit (DDK). It bypasses the involvement of DDK to implement a portable executable file of kernel level for a Windows system software developer. For us, only one instrument of DriverStudio is important, SoftICE; this debugger can be used to trace every portable executable file, a PE file for user mode level or a PE file for kernel mode level.

    Figure 1: SoftICE Window

    EAX=00000000EBX=7FFDD000 ECX=0007FFB0 EDX=7C90EB94 ESI=FFFFFFFF EDI=7C919738 EBP=0007FFF0 ESP=0007FFC4 EIP=010119E0 o d i s z a p c
    CS=0008 DS=0023 SS=0010 ES=0023 FS=0030 GS=0000
    SS:0007FFC4=87C816D4F
    0023:01013000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ……………. 0023:01013010 01 00 00 00 20 00 00 00-0A 00 00 00 0A 00 00 00 ……………. 0023:01013020 20 00 00 00 00 00 00 00-53 63 69 43 61 6C 63 00 ……..SciCalc. 0023:01013030 00 00 00 00 00 00 00 00-62 61 63 6B 67 72 6F 75 ……..backgrou 0023:01013040 6E 64 00 00 00 00 00 00-2E 00 00 00 00 00 00 00 nd…………..
    0010:0007FFC4 4F 6D 81 7C 38 07 91 7C-FF FF FF FF 00 90 FD 7F Om |8 b.| . 0010:0007FFD4 ED A6 54 80 C8 FF 07 00-E8 B4 F5 81 FF FF FF FF T . 0010:0007FFE4 F3 99 83 7C 58 6D 81 7C-00 00 00 00 00 00 00 00 Xm |…….. 0010:0007FFF4 00 00 00 00 E0 19 01 01-00 00 00 00 00 00 00 00 …. ….
    010119E0 PUSH EBP 010119E1 MOV EBP,ESP 010119E3 PUSH -1 010119E5 PUSH 01001570 010119EA PUSH 01011D60 010119EF MOV EAX,DWORD PTR FS:[0] 010119F5 PUSH EAX 010119F6 MOV DWORD PTR FS:[0],ESP 010119FD ADD ESP,-68 01011A00 PUSH EBX 01011A01 PUSH ESI 01011A02 PUSH EDI 01011A03 MOV DWORD PTR SS:[EBP-18],ESP 01011A06 MOV DWORD PTR SS:[EBP-4],0
    :_

    3.1.2 OllyDbg

    It was about four years ago that I first saw this debugger by chance. For me, it was the best choice; I was not wealthy enough to purchase SoftICE, and at that time, SoftICE only had good functions for DOS, Windows 98, and Windows 2000. I found that this debugger supported all kinds of Windows versions. Therefore, I started to learn it very fast, and now it is my favorite debugger for the Windows OS. It is a debugger that can be used to trace all kinds of portable executable files except a Common Language Infrastructure (CLI) file format in user mode level, by using the Windows debugging API. Oleh Yuschuk, the author, is one of worthiest software developers I have seen in my life. He is a Ukrainian who now lives in Germany. I should mention here that his debugger is the best choice for hacker and cracker parties around the world! It is freeware! You can try it from the OllyDbg Homepage.

     

    Figure 2: OllyDbg CPU Window


    (

    3.1.3 Which parts are important in a debugger interface?

    I have introduced two debuggers without talking about how you can employ them, and also which parts you should pay attention to. Regarding using debuggers, I refer you to their instructions in help documents. However, I want to explain briefly the important parts of a debugger; of course, I am talking about low-level debuggers, or in other words, machine-language debuggers of the x86 CPU families.

    All of low-level debuggers consist of the following subdivisions:

    1. Registers viewer.
      EAX
      ECX
      EDX
      EBX
      ESP
      EBP
      ESI
      EDI
      EIP

      o d t s z a p c

    2. Disassembler or Code viewer.
      010119E0 PUSH EBP010119E1 MOV EBP,ESP010119E3 PUSH -1010119E5 PUSH 01001570010119EA PUSH 01011D60010119EF MOV EAX,DWORD PTR FS:[0]010119F5 PUSH EAX010119F6 MOV DWORD PTR FS:[0],ESP010119FD ADD ESP,-6801011A00 PUSH EBX01011A01 PUSH ESI01011A02 PUSH EDI01011A03 MOV DWORD PTR SS:[EBP-18],ESP01011A06 MOV DWORD PTR SS:[EBP-4],0
    3. Memory watcher.
      0023:01013000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ……………. 0023:01013010 01 00 00 00 20 00 00 00-0A 00 00 00 0A 00 00 00 ……………. 0023:01013020 20 00 00 00 00 00 00 00-53 63 69 43 61 6C 63 00 ……..SciCalc. 0023:01013030 00 00 00 00 00 00 00 00-62 61 63 6B 67 72 6F 75 ……..backgrou 0023:01013040 6E 64 00 00 00 00 00 00-2E 00 00 00 00 00 00 00 nd…………..

       

    4. Stack viewer.
      0010:0007FFC4 4F 6D 81 7C 38 07 91 7C-FF FF FF FF 00 90 FD 7F Om |8 b.| . 0010:0007FFD4 ED A6 54 80 C8 FF 07 00-E8 B4 F5 81 FF FF FF FF T . 0010:0007FFE4 F3 99 83 7C 58 6D 81 7C-00 00 00 00 00 00 00 00 Xm |…….. 0010:0007FFF4 00 00 00 00 E0 19 01 01-00 00 00 00 00 00 00 00 …. ….
    5. Command line, command buttons, or shortcut keys to follow the debugging process.
      Command SoftICE OllyDbg
      Run F5 F9
      Step Into F11 F7
      Step Over F10 F8
      Set Break Point F8 F2

    You can compare Figures 1 and 2 to distinguish the difference between SoftICE and OllyDbg. When you want to trace a PE file, you should mostly consider these five subdivisions. Furthermore, every debugger comprises of some other useful parts; you should discover them by yourself.

    3.2 Disassembler

    You can consider OllyDbg and SoftICE to be excellent disassemblers, but I also want to introduce another disassembler tool that is famous in the reverse engineering world.

    3.2.1 Proview disassembler

    Proview or PVDasm is an admirable disassembler by the Reverse-Engineering-Community; it is still under development and bug fixing. You can find its disassmbler source engine and employ it to create your own disassembler.

    3.2.2 W32Dasm

    W32DASM can disassemble both 16- and 32-bit executable file formats. In addition to its disassembling ability, you can employ it to analyze import, export, and resource data directories data.

    3.2.3 IDA Pro

    All reverse-engineering experts know that IDA Pro can be used to investigate, not only x86 instructions, but that of various kinds of CPU types like AVR, PIC, and so forth. It can illustrate the assembly source of a portable executable file by using colored graphics and tables, and is very useful for any newbie in this area. Furthermore, it has the capability to trace an executable file inside the user mode level in the same way as OllyDbg.

    3.3 Some Useful Tools

    A good PE tools developer is conversant with the tools that save his time, so I recommend that you select some appropriate instruments to investigate the base information under a portable executable file.

    3.3.1 LordPE

    LordPE by y0da is still the first choice to retrieve PE file information with the possibility to modify them.

    3.3.2 PEiD

    PE iDentifier is valuable to identify the type of compilers, packers, and cryptors of PE files. As of now, it can detect more than 500 different signature types of PE files.

    3.3.3 Resource Hacker

    Resource Hacker can be employed to modify resource directory information; icon, menu, version info, string table, and so on.

    3.3.4 WinHex

    WinHex, it is clear what you can do with this tool.

    3.3.5 CFF Explorer

    Eventually, CFF Explorer by Ntoskrnl is what you want to have as a PE Utility tool in your arsenal; it supports PE32/64, PE rebuild included Common Language Infrastructure (CLI) file. In other words, the .NET file, a resource modifier, and much more facilities which can not be found in others. Just try to discover every unimaginable option by hand.

    4 Add a New Section and Change the OEP

    You are ready to do the first step of making your project. I have provided a library to add a new section and rebuild the portable executable file. Before starting, I wnat you to get familiar with the headers of a PE file, by using OllyDbg. You should first open a PE file; that pops up a menu, View->Executable file. Again, you get a popup menu: Special->PE header. You will observe a scene similar to Figure 3. Now, come to the Main Menu View->Memory, and try to distinguish the sections inside the Memory map window.

    Figure 3

    00000000000000020000000400000006000000080000000A0000000C0000000E00000010000000120000001400000016000000180000001A0000001C0000001D0000001E0000001F000000200000002100000022000000230000002400000025000000260000002700000028000000290000002A0000002B0000002C0000002D0000002E0000002F000000300000003100000032000000330000003400000035000000360000003700000038000000390000003A0000003B0000003C

     4D 5A 9000 0300 0000 0400 0000 FFFF 0000 B800 0000 0000 0000 4000 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0000000
     ASCII "MZ" DW 0090 DW 0003 DW 0000 DW 0004 DW 0000 DW FFFF DW 0000 DW 00B8 DW 0000 DW 0000 DW 0000 DW 0040 DW 0000 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DB 00 DD 000000F0
     DOS EXE Signature DOS_PartPag = 90 (144.) DOS_PageCnt = 3 DOS_ReloCnt = 0 DOS_HdrSize = 4 DOS_MinMem = 0 DOS_MaxMem = FFFF (65535.) DOS_ReloSS = 0 DOS_ExeSP = B8 DOS_ChkSum = 0 DOS_ExeIP = 0 DOS_ReloCS = 0 DOS_TablOff = 40 DOS_Overlay = 0 Offset to PE signature

     

    I want to explain how you can plainly change the Offset of Entry Point (OEP) in your sample file, CALC.EXE of Windows XP. First, by using a PE Tool, and also using your PE Viewer, you find OEP, 0x00012475, and Image Base, 0x01000000. This value of OEP is the Relative Virtual Address, so the Image Base value is used to convert it to the Virtual Address.

    Virtual_Address = Image_Base + Relative_Virtual_Address

    DWORD OEP_RVA = image_nt_headers->   OptionalHeader.AddressOfEntryPoint ;// OEP_RVA = 0x00012475DWORD OEP_VA = image_nt_headers->   OptionalHeader.ImageBase + OEP_RVA ;// OEP_VA = 0x01000000 + 0x00012475 = 0x01012475

    PE Maker: Step 1

    Download pemaker1.zip and test1.zip from the files at the end of this article.

    DynLoader(), in loader.cpp, is reserved for the data of the new section—in other words, the Loader.

    DynLoader Step 1

    __stdcall void DynLoader(){_asm{//----------------------------------    DWORD_TYPE(DYN_LOADER_START_MAGIC)//----------------------------------    MOV EAX,01012475h // << Original OEP    JMP EAX//----------------------------------    DWORD_TYPE(DYN_LOADER_END_MAGIC)//----------------------------------}}

    Unfortunately, this source can only be applied for the sample test file. You should complete it by saving the value of the original OEP in the new section, and use it to reach the real OEP. I have accomplished it in Step 2 (Section 5).

    4.1 Retrieve and Rebuild PE file

    I have made a simple class library to recover PE information and to use it in a new PE file.

    CPELibrary Class Step 1

    //----------------------------------------------------------------class CPELibrary{private:    //-----------------------------------------    PCHAR                   pMem;    DWORD                   dwFileSize;    //-----------------------------------------protected:    //-----------------------------------------    PIMAGE_DOS_HEADER       image_dos_header;    PCHAR                   pDosStub;    DWORD                   dwDosStubSize, dwDosStubOffset;    PIMAGE_NT_HEADERS       image_nt_headers;    PIMAGE_SECTION_HEADER   image_section_header[MAX_SECTION_NUM];    PCHAR                   image_section[MAX_SECTION_NUM];    //-----------------------------------------protected:    //-----------------------------------------    DWORD PEAlign(DWORD dwTarNum,DWORD dwAlignTo);    void AlignmentSections();    //-----------------------------------------    DWORD Offset2RVA(DWORD dwRO);    DWORD RVA2Offset(DWORD dwRVA);    //-----------------------------------------    PIMAGE_SECTION_HEADER ImageRVA2Section(DWORD dwRVA);    PIMAGE_SECTION_HEADER ImageOffset2Section(DWORD dwRO);    //-----------------------------------------    DWORD ImageOffset2SectionNum(DWORD dwRVA);    PIMAGE_SECTION_HEADER AddNewSection(char* szName,DWORD dwSize);    //-----------------------------------------public:    //-----------------------------------------    CPELibrary();    ~CPELibrary();    //-----------------------------------------    void OpenFile(char* FileName);    void SaveFile(char* FileName);    //-----------------------------------------};

    In Table 1, the usage of image_dos_header, pDosStub, image_nt_headers, image_section_header [MAX_SECTION_NUM], and image_section[MAX_SECTION_NUM] is clear. You use OpenFile() and SaveFile() to retrieve and rebuild a PE file. Furthermore, AddNewSection() is employed to create the new section, the important step.


    4.2 Create data for the new section

    Full Size Image)

    You can comprehend the difference between incremental link and no-incremental link by looking at the following picture:

    To acquire the virtual address of DynLoader(), you obtain the virtual address of JMP pemaker.DynLoader in the incremental link, but by no-incremental link, the real virtual address is gained by the following code:

    DWORD dwVA= (DWORD) DynLoader;

    This setting is more critical in the incremental link when you try to find the beginning and ending of the Loader, DynLoader(), by CPECryptor::ReturnToBytePtr():

    void* CPECryptor::ReturnToBytePtr(void* FuncName, DWORD findstr){    void* tmpd;    __asm   {        mov eax, FuncName        jmp dfhjg:    inc eaxdf:     mov ebx, [eax]        cmp ebx, findstr        jnz hjg        mov tmpd, eax    }    return tmpd;}

    In pecrypt.cpp, I have represented another class, CPECryptor, to comprise the data of the new section. Nevertheless, the data of the new section is created by DynLoader() in loader.cpp, DynLoader Step 1. You use the CPECryptor class to enter this data in to the new section, and also some other stuff.

    CPECryptor Class Step 1

    //----------------------------------------------------------------class CPECryptor: public CPELibrary{private:    //----------------------------------------    PCHAR pNewSection;    //----------------------------------------    DWORD GetFunctionVA(void* FuncName);    void* ReturnToBytePtr(void* FuncName, DWORD findstr);    //----------------------------------------protected:    //----------------------------------------public:    //----------------------------------------    void CryptFile(int(__cdecl *callback) (unsigned int,                                           unsigned int));    //----------------------------------------};//----------------------------------------------------------------

    4.3 Some notes regarding creating a new PE file

    • Align the VirtualAddress and the VirtualSize of each section by SectionAlignment:
      image_section_header[i]->VirtualAddress=    PEAlign(image_section_header[i]->VirtualAddress,    image_nt_headers->OptionalHeader.SectionAlignment);image_section_header[i]->Misc.VirtualSize=    PEAlign(image_section_header[i]->Misc.VirtualSize,    image_nt_headers->OptionalHeader.SectionAlignment);
    • Align the PointerToRawData and the SizeOfRawData of each section by FileAlignment:
      image_section_header[i]->PointerToRawData =    PEAlign(image_section_header[i]->PointerToRawData,            image_nt_headers->OptionalHeader.FileAlignment);image_section_header[i]->SizeOfRawData =    PEAlign(image_section_header[i]->SizeOfRawData,            image_nt_headers->OptionalHeader.FileAlignment);
    • Correct the SizeofImage by the virtual size and the virtual address of the last section:
      image_nt_headers->OptionalHeader.SizeOfImage =   image_section_header[LastSection]->VirtualAddress +   image_section_header[LastSection]->Misc.VirtualSize;
    • Set the Bound Import Directory header to zero because this directory is not very important to execute a PE file:
      image_nt_headers->   OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].  VirtualAddress = 0;image_nt_headers->   OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_                                IMPORT].Size = 0;

    4.4 Some notes regarding linking this VC Project

    • Set Linker->General->Enable Incremental Linking to No (/INCREMENTAL:NO).


      (

    5 Store Important Data and Reach the Original OEP

    Right now, we save the Original OEP and also the Image Base in order to reach to the virtual address of OEP. I have reserved a free space at the end of DynLoader() to store them, DynLoader Step 2.

    PE Maker – Step 2

    Download the pemaker2.zip source files from the end of the article.

    DynLoader Step 2

    __stdcall void DynLoader(){_asm{//------------------------------------    DWORD_TYPE(DYN_LOADER_START_MAGIC)//------------------------------------Main_0:    PUSHAD    // get base ebp    CALL Main_1Main_1:    POP EBP    SUB EBP,OFFSET Main_1    MOV EAX,DWORD PTR [EBP+_RO_dwImageBase]    ADD EAX,DWORD PTR [EBP+_RO_dwOrgEntryPoint]    PUSH EAX    RETN // >> JMP to Original OEP//----------------------------------    DWORD_TYPE(DYN_LOADER_START_DATA1)//----------------------------------//----------------------------------    DWORD_TYPE(DYN_LOADER_END_MAGIC)//----------------------------------}}_RO_dwImageBase:                DWORD_TYPE(0xCCCCCCCC)_RO_dwOrgEntryPoint:            DWORD_TYPE(0xCCCCCCCC)

    The new function, CPECryptor::CopyData1(), will implement the copy of the Image Base value and the Offset of Entry Point value into 8 bytes of free space in the loader.

    5.1 Restore the first register’s context

    It is important to recover the Original Context of the thread. You have not yet done it in the DynLoader Step 2 source code. You can modify the source of DynLoader() to repossess the first Context.

    __stdcall void DynLoader(){_asm{//------------------------------------    DWORD_TYPE(DYN_LOADER_START_MAGIC)//------------------------------------Main_0:    PUSHAD// Save the registers context in stack    CALL Main_1Main_1:    POP EBP// Get Base EBP    SUB EBP,OFFSET Main_1    MOV EAX,DWORD PTR [EBP+_RO_dwImageBase]    ADD EAX,DWORD PTR [EBP+_RO_dwOrgEntryPoint]    MOV DWORD PTR [ESP+1Ch],EAX // pStack.Eax <- EAX    POPAD // Restore the first registers context from stack    PUSH EAX    XOR  EAX, EAX    RETN // >> JMP to Original OEP//----------------------------------    DWORD_TYPE(DYN_LOADER_START_DATA1)//----------------------------------_RO_dwImageBase:                DWORD_TYPE(0xCCCCCCCC)_RO_dwOrgEntryPoint:            DWORD_TYPE(0xCCCCCCCC)//----------------------------------    DWORD_TYPE(DYN_LOADER_END_MAGIC)//----------------------------------}}

    5.2 Restore the original stack

    You also can recover the original stack by setting the value of the beginning stack + 0x34 to the Original OEP, but it is not very important. Nevertheless, in the following code, I have accomplished the loader code by a simple trick to reach the OEP in addition to redecorating the stack. You can observe the implementation by tracing using OllyDbg or SoftICE.

    __stdcall void DynLoader(){_asm{//----------------------------------    DWORD_TYPE(DYN_LOADER_START_MAGIC)//----------------------------------Main_0:    PUSHAD    // Save the registers context in stack    CALL Main_1Main_1:    POP EBP    SUB EBP,OFFSET Main_1    MOV EAX,DWORD PTR [EBP+_RO_dwImageBase]    ADD EAX,DWORD PTR [EBP+_RO_dwOrgEntryPoint]    MOV DWORD PTR [ESP+54h],EAX    // pStack.Eip <- EAX    POPAD    // Restore the first registers context from stack    CALL _OEP_Jump    DWORD_TYPE(0xCCCCCCCC)_OEP_Jump:    PUSH EBP    MOV EBP,ESP    MOV EAX,DWORD PTR [ESP+3Ch]    // EAX <- pStack.Eip    MOV DWORD PTR [ESP+4h],EAX     // _OEP_Jump RETURN pointer <- EAX    XOR EAX,EAX    LEAVE    RETN//----------------------------------    DWORD_TYPE(DYN_LOADER_START_DATA1)//----------------------------------_RO_dwImageBase:                DWORD_TYPE(0xCCCCCCCC)_RO_dwOrgEntryPoint:            DWORD_TYPE(0xCCCCCCCC)//----------------------------------    DWORD_TYPE(DYN_LOADER_END_MAGIC)//----------------------------------}}

    5.3 Approach OEP by structured exception handling

    try-except statement in C++ clarifies the operation of structured exception handling. Besides the assembly code of this code, it elucidates the structured exception handler installation, the raise of an exception, and the exception handler function.

    An exception is generated when a program falls into a fault code execution and an error happens, so in such a special condition, the program immediately jumps to a function called the exception handler from exception handler list of the Thread Information Block.

    The next example of a

    #include "stdafx.h"#include "windows.h"void RAISE_AN_EXCEPTION(){_asm{    INT 3    INT 3    INT 3    INT 3}}int _tmain(int argc, _TCHAR* argv[]){    __try    {        __try{            printf("1: Raise an Exception\n");            RAISE_AN_EXCEPTION();        }        __finally        {            printf("2: In Finally\n");        }    }    __except( printf("3: In Filter\n"), EXCEPTION_EXECUTE_HANDLER )    {        printf("4: In Exception Handler\n");    }    return 0;}
    ; main()00401000: PUSH EBP00401001: MOV EBP,ESP00401003: PUSH -100401005: PUSH 00407160; __try {; the structured exception handler (SEH) installation 0040100A: PUSH _except_handler30040100F: MOV EAX,DWORD PTR FS:[0]00401015: PUSH EAX00401016: MOV DWORD PTR FS:[0],ESP0040101D: SUB ESP,800401020: PUSH EBX00401021: PUSH ESI00401022: PUSH EDI00401023: MOV DWORD PTR SS:[EBP-18],ESP;     __try {00401026: XOR ESI,ESI00401028: MOV DWORD PTR SS:[EBP-4],ESI0040102B: MOV DWORD PTR SS:[EBP-4],100401032: PUSH OFFSET "1: Raise an Exception"00401037: CALL printf0040103C: ADD ESP,4; the raise a exception, INT 3 exception; RAISE_AN_EXCEPTION()0040103F: INT300401040: INT300401041: INT300401042: INT3;     } __finally {00401043: MOV DWORD PTR SS:[EBP-4],ESI00401046: CALL 0040104D0040104B: JMP 004010800040104D: PUSH OFFSET "2: In Finally"00401052: CALL printf00401057: ADD ESP,40040105A: RETN;     }; }; __except( 0040105B: JMP 004010800040105D: PUSH OFFSET "3: In Filter"00401062: CALL printf00401067: ADD ESP,40040106A: MOV EAX,1 ; EXCEPTION_EXECUTE_HANDLER = 10040106F: RETN;     , EXCEPTION_EXECUTE_HANDLER ); {; the exception handler funtion00401070: MOV ESP,DWORD PTR SS:[EBP-18]00401073: PUSH OFFSET "4: In Exception Handler"00401078: CALL printf0040107D: ADD ESP,4; }00401080: MOV DWORD PTR SS:[EBP-4],-10040108C: XOR EAX,EAX; restore previous SEH0040108E: MOV ECX,DWORD PTR SS:[EBP-10]00401091: MOV DWORD PTR FS:[0],ECX00401098: POP EDI00401099: POP ESI0040109A: POP EBX0040109B: MOV ESP,EBP0040109D: POP EBP0040109E: RETN

    Make a Win32 console project, and link and run the preceding C++ code, to perceive the result:

    1: Raise an Exception
    3: In Filter
    2: In Finally
    4: In Exception Handler
    _

    This program runs the exception expression, printf("3: In Filter\n");, when an exception happens—in this example, the INT 3 exception. You can employ other kinds of exception too. In OllyDbg, Debugging options->Exceptions, you can see a short list of different types of exceptions.

    5.3.1 Implement Exception Handler

    You want to construct a structured exception handler to reach OEP. Now, I think you have distinguished the SEH installation, the exception raise, and the exception expression filter, by foregoing the assembly code. To establish your exception handler approach, you need to comprise the following codes:

    • SEH installation:
      LEA EAX,[EBP+_except_handler1_OEP_Jump]PUSH EAXPUSH DWORD PTR FS:[0]MOV DWORD PTR FS:[0],ESP
    • An Exception Raise:
      INT 3
    • Exception handler expression filter:
      _except_handler1_OEP_Jump:   PUSH EBP   MOV EBP,ESP   ...   // EXCEPTION_CONTINUE_SEARCH = 0   MOV EAX, EXCEPTION_CONTINUE_SEARCH   LEAVE   RETN

    So, you yearn to make the ensuing C++ code in assembly language to inaugurate your engine to approach the Offset of the Entry Point by SEH.

    __try    // SEH installation{    __asm    {        INT 3    // An Exception Raise    }}__except( ..., EXCEPTION_CONTINUE_SEARCH ){}// Exception handler expression filter

    In assembly code…

        ; ----------------------------------------------------    ; the structured exception handler (SEH) installation    ; __try {    LEA EAX,[EBP+_except_handler1_OEP_Jump]    PUSH EAX    PUSH DWORD PTR FS:[0]    MOV DWORD PTR FS:[0],ESP    ; ----------------------------------------------------    ; the raise a INT 3 exception    INT 3    INT 3    INT 3    INT 3    ; }    ; __except( ...     ; ----------------------------------------------------    ; exception handler expression filter_except_handler1_OEP_Jump:    PUSH EBP    MOV EBP,ESP    ...    MOV EAX, EXCEPTION_CONTINUE_SEARCH ; EXCEPTION_CONTINUE_SEARCH = 0    LEAVE    RETN    ; , EXCEPTION_CONTINUE_SEARCH ) { }

    The exception value, __except(..., Value), determines how the exception is handled. It can have three values: 1, 0, -1. To understand them, refer to the try-except statement description in the MSDN library. You set it to EXCEPTION_CONTINUE_SEARCH (0), not to run the exception handler function; therefore, by this value, the exception is not recognized. It is simply ignored, and the thread continues its code execution.

    How the SEH installation is implemented

    As you perceived from the illustrated code, the SEH installation is done by the FS segment register. Microsoft Windows 32 bit uses the FS segment register as a pointer to the data block of the main thread. The first 0x1C bytes comprise the information of the Thread Information Block (TIB). Therefore, FS:[00h] refers to ExceptionList of the main thread, Table 3. In your code, you have pushed the pointer to _except_handler1_OEP_Jump in the stack and changed the value of ExceptionList, FS:[00h], to the beginning of the stack, ESP.

    Thread Information Block (TIB)

    typedef struct _NT_TIB32 {   DWORD ExceptionList;   DWORD StackBase;   DWORD StackLimit;   DWORD SubSystemTib;   union {      DWORD FiberData;      DWORD Version;   };   DWORD ArbitraryUserPointer;   DWORD Self;} NT_TIB32, *PNT_TIB32;

    Table 3: FS segment register and Thread Information Block

    DWORD PTR FS:[00h] ExceptionList
    DWORD PTR FS:[04h] StackBase
    DWORD PTR FS:[08h] StackLimit
    DWORD PTR FS:[0Ch] SubSystemTib
    DWORD PTR FS:[10h] FiberData / Version
    DWORD PTR FS:[14h] ArbitraryUserPointer
    DWORD PTR FS:[18h] Self
    5.3.2 Attain OEP by adjusting the Thread Context

    In this part, you effectuate your performance by accomplishing the OEP approach. You change the Context of the thread and ignore every simple exception handling, and let the thread continue the execution, but in the original OEP!

     

    When an exception happens, the context of the processor during the time of the exception is saved in the stack. Through

    MOV EAX, ContextRecordMOV EDI, dwOEP                   ; EAX <- dwOEPMOV DWORD PTR DS:[EAX+0B8h], EDI ; pContext.Eip <- EAX

    Win32 Thread Context structure

    #define MAXIMUM_SUPPORTED_EXTENSION     512typedef struct _CONTEXT {    //-----------------------------------------    DWORD ContextFlags;    //-----------------------------------------    DWORD   Dr0;    DWORD   Dr1;    DWORD   Dr2;    DWORD   Dr3;    DWORD   Dr6;    DWORD   Dr7;    //-----------------------------------------    FLOATING_SAVE_AREA FloatSave;    //-----------------------------------------    DWORD   SegGs;    DWORD   SegFs;    DWORD   SegEs;    DWORD   SegDs;    //-----------------------------------------    DWORD   Edi;    DWORD   Esi;    DWORD   Ebx;    DWORD   Edx;    DWORD   Ecx;    DWORD   Eax;    //-----------------------------------------    DWORD   Ebp;    DWORD   Eip;    DWORD   SegCs;    DWORD   EFlags;    DWORD   Esp;    DWORD   SegSs;    //-----------------------------------------    BYTE    ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];    //----------------------------------------} CONTEXT,*LPCONTEXT;

    Table 4: CONTEXT

    Context Flags 0×00000000 ContextFlags

    Context Debug Registers

    0×00000004 Dr0
    0×00000008 Dr1
    0x0000000C Dr2
    0×00000010 Dr3
    0×00000014 Dr6
    0×00000018 Dr7

    Context Floating Point

    0x0000001C FloatSave StatusWord
    0×00000020 StatusWord
    0×00000024 TagWord
    0×00000028 ErrorOffset
    0x0000002C ErrorSelector
    0×00000030 DataOffset
    0×00000034 DataSelector
    0×00000038

    0×00000087
    RegisterArea [0x50]
    0×00000088 Cr0NpxState
    Context Segments 0x0000008C SegGs
    0×00000090 SegFs
    0×00000094 SegEs
    0×00000098 SegDs
    Context Integer 0x0000009C Edi
    0x000000A0 Esi
    0x000000A4 Ebx
    0x000000A8 Edx
    0x000000AC Ecx
    0x000000B0 Eax
    Context Control 0x000000B4 Ebp
    0x000000B8 Eip
    0x000000BC SegCs
    0x000000C0 EFlags
    0x000000C4 Esp
    0x000000C8 SegSs
    Context Extended Registers

    0x000000CC

    0x000002CB

    ExtendedRegisters[0x200]

    By the following code, you have accomplished the main purpose of coming to OEP by the structured exception handler:

    __stdcall void DynLoader(){_asm{//----------------------------------    DWORD_TYPE(DYN_LOADER_START_MAGIC)//----------------------------------Main_0:    PUSHAD  // Save the registers context in stack    CALL Main_1Main_1:    POP EBP    SUB EBP,OFFSET Main_1 // Get Base EBP    MOV EAX,DWORD PTR [EBP+_RO_dwImageBase]    ADD EAX,DWORD PTR [EBP+_RO_dwOrgEntryPoint]    MOV DWORD PTR [ESP+10h],EAX    // pStack.Ebx <- EAX    LEA EAX,[EBP+_except_handler1_OEP_Jump]    MOV DWORD PTR [ESP+1Ch],EAX    // pStack.Eax <- EAX    POPAD  // Restore the first registers context from stack    //----------------------------------------------------    // the structured exception handler (SEH) installation    PUSH EAX    XOR  EAX, EAX    PUSH DWORD PTR FS:[0]       // NT_TIB32.ExceptionList    MOV DWORD PTR FS:[0],ESP    // NT_TIB32.ExceptionList <-ESP    //----------------------------------------------------    // the raise a INT 3 exception    DWORD_TYPE(0xCCCCCCCC)    //--------------------------------------------------------// -------- exception handler expression filter ----------_except_handler1_OEP_Jump:    PUSH EBP    MOV EBP,ESP    //------------------------------    MOV EAX,DWORD PTR SS:[EBP+010h]   // PCONTEXT: pContext <- EAX    //==============================    PUSH EDI    // restore original SEH    MOV EDI,DWORD PTR DS:[EAX+0C4h]    // pContext.Esp    PUSH DWORD PTR DS:[EDI]    POP DWORD PTR FS:[0]    ADD DWORD PTR DS:[EAX+0C4h],8    // pContext.Esp    //------------------------------    // set the Eip to the OEP    MOV EDI,DWORD PTR DS:[EAX+0A4h] // EAX <- pContext.Ebx    MOV DWORD PTR DS:[EAX+0B8h],EDI // pContext.Eip <- EAX    //------------------------------    POP EDI    //==============================    MOV EAX, EXCEPTION_CONTINUE_SEARCH    LEAVE    RETN//----------------------------------    DWORD_TYPE(DYN_LOADER_START_DATA1)//----------------------------------_RO_dwImageBase:                DWORD_TYPE(0xCCCCCCCC)_RO_dwOrgEntryPoint:            DWORD_TYPE(0xCCCCCCCC)//----------------------------------    DWORD_TYPE(DYN_LOADER_END_MAGIC)//----------------------------------}}

    6 Build an Import Table and Reconstruct the Original Import Table

    There are two ways to use the Windows dynamic link library (DLL) in Windows application programming:

    • Using Windows libraries by additional dependencies


      (

      Full Size Image)

    • Using Windows dynamic link libraries in run-time:
      // DLL function signaturetypedef HGLOBAL (*importFunction_GlobalAlloc)(UINT, SIZE_T);...importFunction_GlobalAlloc __GlobalAlloc;// Load DLL fileHINSTANCE hinstLib = LoadLibrary("Kernel32.dll");if (hinstLib == NULL){   // Error - unable to load DLL}// Get function pointer__GlobalAlloc =   (importFunction_GlobalAlloc)GetProcAddress(hinstLib,                                              "GlobalAlloc");if (addNumbers == NULL){    // Error - unable to find DLL function}FreeLibrary(hinstLib);

    When you make a Windows application project, the linker includes at least kernel32.dll in the base dependencies of your project. Without LoadLibrary() and GetProcAddress() of Kernel32.dll, you cannot load a DLL at run time. The dependencies information is stored in the import table section. By using Dependency Walker, it is not so difficult to observe the DLL module and the functions that are imported into a PE file.

    You attempt to establish your custom import table to conduct your project. Furthermore, you have to fix up the original import table at the end to run the real code of the program.

    PE Maker: Step 3

    Download the pemaker3.zip source files from the end of the article.

    6.1 Construct the Client Import Table

    I strongly advise that you to read Section 6.4 of the Microsoft Portable Executable and the Common Object File Format Specification document. This section contains the principal information to comprehend the import table performance. The import table data is accessible by a second data directory of the optional header from PE headers, so you can access it by using the following code:

    DWORD dwVirtualAddress = image_nt_headers->   OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].      VirtualAddress;DWORD dwSize = image_nt_headers->   OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].      Size;

    The VirtualAddress refers to structures by IMAGE_IMPORT_DESCRIPTOR. This structure contains the pointer to the imported DLL name and the relative virtual address of the first thunk.

    typedef struct _IMAGE_IMPORT_DESCRIPTOR {    union {        DWORD   Characteristics;        DWORD   OriginalFirstThunk;    };    DWORD   TimeDateStamp;    DWORD   ForwarderChain;    DWORD   Name;         // the imported DLL name    DWORD   FirstThunk;   // the relative virtual address of the                          // first thunk} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;

    When a program is running, the Windows Task Manager sets the thunks by the virtual address of the function. The virtual address is found by the name of the function. At first, the thunks hold the relative virtual address of the function name, as shown in Table 5; during execution, they are fixed up by the virtual address of the functions (see Table 6).

    Table 5: The Import Table in a file image

    IMAGE_IMPORT_
    DESCRIPTOR[0]
    OriginalFirstThunk    
    TimeDateStamp
    ForwarderChain
    Name_RVA ——> "kernel32.dll",0
    FirstThunk_RVA ——> proc_1_name_RVA ——> 0,0,"LoadLibraryA",0
      proc_2_name_RVA ——> 0,0,"GetProcAddress",0
    proc_3_name_RVA ——> 0,0,"GetModuleHandleA",0
       
    IMAGE_IMPORT_
    DESCRIPTOR[1]
     
    ...  
    IMAGE_IMPORT_
    DESCRIPTOR[n]
     

    Table 6: The Import Table in virtual memory

    IMAGE_IMPORT_DESCRIPTOR[0] OriginalFirstThunk  
    TimeDateStamp
    ForwarderChain
    Name_RVA ------> "kernel32.dll",0
    FirstThunk_RVA ------> proc_1_VA
      proc_2_VA
    proc_3_VA
    ...
    IMAGE_IMPORT_DESCRIPTOR[1]  
    ...  
    IMAGE_IMPORT_DESCRIPTOR[n]  

    You want to make a simple import table to import LoadLibrary(), and GetProcAddress() from Kernel32.dll. You need these two essential API functions to cover other API functions in run-time. The following assembly code shows how easily you can reach your solution:

    0101F000: 00000000 ; OriginalFirstThunk0101F004: 00000000 ; TimeDateStamp0101F008: 00000000 ; ForwarderChain0101F00C: 0001F034 ; Name;       ImageBase + 0001F034                                 -> 0101F034 -> "Kernel32.dll",00101F010: 0001F028 ; FirstThunk; ImageBase + 0001F028 -> 0101F0280101F014: 000000000101F018: 000000000101F01C: 000000000101F020: 000000000101F024: 000000000101F028: 0001F041 ; ImageBase + 0001F041 -> 0101F041                     -> 0,0,"LoadLibraryA",00101F02C: 0001F050 ; ImageBase + 0001F050 -> 0101F050                     -> 0,0,"GetProcAddress",00101F030: 000000000101F034: 'K' 'e' 'r' 'n' 'e' 'l' '3' '2' '.' 'd' 'l' 'l' 0001F041: 00 00 'L' 'o' 'a' 'd' 'L' 'i' 'b' 'r' 'a' 'r' 'y' 'A'0001F050: 00 00 'G' 'e' 't' 'P' 'r' 'o' 'c' 'A' 'd' 'd' 'r' 'e' 's'          's' 00 0000

    After running…

    0101F000: 00000000 ; OriginalFirstThunk0101F004: 00000000 ; TimeDateStamp0101F008: 00000000 ; ForwarderChain0101F00C: 0001F034 ; Name;       ImageBase + 0001F034                                 -> 0101F034 -> "Kernel32.dll",00101F010: 0001F028 ; FirstThunk; ImageBase + 0001F028 -> 0101F0280101F014: 000000000101F018: 000000000101F01C: 000000000101F020: 000000000101F024: 000000000101F028: 7C801D77 ; -> Kernel32.LoadLibrary()0101F02C: 7C80AC28 ; -> Kernel32.GetProcAddress()0101F030: 000000000101F034: 'K' 'e' 'r' 'n' 'e' 'l' '3' '2' '.' 'd' 'l' 'l' 0001F041: 00 00 'L' 'o' 'a' 'd' 'L' 'i' 'b' 'r' 'a' 'r' 'y' 'A'0001F050: 00 00 'G' 'e' 't' 'P' 'r' 'o' 'c' 'A' 'd' 'd' 'r' 'e' 's'          's' 00 0000

    I have prepared a class library to make every import table by using a client string table. The CITMaker class library in itmaker.h; it will build an import table by sz_IT_EXE_strings and also the relative virtual address of the import table.

    static const char *sz_IT_EXE_strings[]={    "Kernel32.dll",    "LoadLibraryA",    "GetProcAddress",    0,,    0,};

    You subsequently employ this class library to establish an import table to support DLLs and OCXs, so this is a general library to present all possible import tables easily. The next step is clarified in the following code.

    CITMaker *ImportTableMaker = new CITMaker( IMPORT_TABLE_EXE );...pimage_section_header=AddNewSection( ".xxx", dwNewSectionSize );// build import table by the current virtual addressImportTableMaker->Build( pimage_section_header->VirtualAddress );memcpy( pNewSection, ImportTableMaker->pMem,ImportTableMaker->dwSize );...memcpy( image_section[image_nt_headers->FileHeader.NumberOfSections-1],        pNewSection,        dwNewSectionSize );...image_nt_headers->OptionalHeader.  DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress  = pimage_section_header->VirtualAddress;image_nt_headers->OptionalHeader.  DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size  = ImportTableMaker->dwSize;...delete ImportTableMaker;

    The import table is copied at the beginning of the new section, and the relevant data directory is adjusted to the relative virtual address of the new section and the size of the new import table.

    6.2 Using other API functions at run time

    At this time, you can load other DLLs and find the process address of other functions by using LoadLibrary() and GetProcAddress():

    lea edi, @"Kernel32.dll"//-------------------push edimov eax,offset _p_LoadLibrarycall [ebp+eax] //LoadLibrary(lpLibFileName);//-------------------mov esi,eax    // esi -> hModulelea edi, @"GetModuleHandleA"//-------------------push edipush esimov eax,offset _p_GetProcAddresscall [ebp+eax] //GetModuleHandle=GetProcAddress(hModule, lpProcName);//--------------------

     LoadLibrary() and GetProcAddress() aid you in your effort to reach your intention.

    I want to have a complete imported function table similar in performance done in a real EXE file. If you look inside a PE file, you will discover that an API call is done by an indirection jump through the virtual address of the API function:

    JMP DWORD PTR [XXXXXXXX]

    ...0101F028: 7C801D77      ; Virtual Address of kernel32.LoadLibrary()...0101F120: JMP DWORD PTR [0101F028]...0101F230: CALL 0101F120 ;  JMP to kernel32.LoadLibrary...

    It makes it easy to expand the other part of your project by this performance, so you construct two data tables: the first for API virtual addresses, and the second for the JMP [XXXXXXXX].

    #define __jmp_api               byte_type(0xFF) byte_type(0x25)__asm{...//----------------------------------------------------------------_p_GetModuleHandle:             dword_type(0xCCCCCCCC)_p_VirtualProtect:              dword_type(0xCCCCCCCC)_p_GetModuleFileName:           dword_type(0xCCCCCCCC)_p_CreateFile:                  dword_type(0xCCCCCCCC)_p_GlobalAlloc:                 dword_type(0xCCCCCCCC)//----------------------------------------------------------------_jmp_GetModuleHandle:           __jmp_api   dword_type(0xCCCCCCCC)_jmp_VirtualProtect:            __jmp_api   dword_type(0xCCCCCCCC)_jmp_GetModuleFileName:         __jmp_api   dword_type(0xCCCCCCCC)_jmp_CreateFile:                __jmp_api   dword_type(0xCCCCCCCC)_jmp_GlobalAlloc:               __jmp_api   dword_type(0xCCCCCCCC)//----------------------------------------------------------------...}

    In the succeeding code, you have concluded your ambition to install a custom internal import table! (You cannot call it import table.)

        ...    lea edi,[ebp+_p_szKernel32]    lea ebx,[ebp+_p_GetModuleHandle]    lea ecx,[ebp+_jmp_GetModuleHandle]    add ecx,02h_api_get_lib_address_loop:        push ecx        push edi        mov eax,offset _p_LoadLibrary        call [ebp+eax]    //LoadLibrary(lpLibFileName);        pop ecx        mov esi,eax       // esi -> hModule        push edi        call __strlen        add esp,04h        add edi,eax_api_get_proc_address_loop:            push ecx            push edi            push esi            mov eax,offset _p_GetProcAddress            //GetModuleHandle=GetProcAddress(hModule, lpProcName);            call [ebp+eax]            pop ecx            mov [ebx],eax            mov [ecx],ebx    // JMP DWORD PTR [XXXXXXXX]            add ebx,04h            add ecx,06h            push edi            call __strlen            add esp,04h            add edi,eax            mov al,byte ptr [edi]        test al,al        jnz _api_get_proc_address_loop        inc edi        mov al,byte ptr [edi]    test al,al    jnz _api_get_lib_address_loop    ...

    6.3 Fix up the Original Import Table

    To run the program again, you should fix up the thunks of the actual import table; otherwise, you have a corrupted target PE file. Your code must correct all of the thunks the same as Table 5 to Table 6. Once more,

        ...    mov ebx,[ebp+_p_dwImportVirtualAddress]    test ebx,ebx    jz _it_fixup_end    mov esi,[ebp+_p_dwImageBase]    add ebx,esi             // dwImageBase + dwImportVirtualAddress_it_fixup_get_lib_address_loop:        mov eax,[ebx+00Ch]  // image_import_descriptor.Name        test eax,eax        jz _it_fixup_end        mov ecx,[ebx+010h]  // image_import_descriptor.FirstThunk        add ecx,esi        mov [ebp+_p_dwThunk],ecx    // dwThunk        mov ecx,[ebx]       // image_import_descriptor.Characteristics        test ecx,ecx        jnz _it_fixup_table            mov ecx,[ebx+010h]_it_fixup_table:        add ecx,esi        mov [ebp+_p_dwHintName],ecx    // dwHintName        add eax,esi  // image_import_descriptor.Name + dwImageBase = ModuleName        push eax     // lpLibFileName        mov eax,offset _p_LoadLibrary        call [ebp+eax]               // LoadLibrary(lpLibFileName);        test eax,eax        jz _it_fixup_end        mov edi,eax_it_fixup_get_proc_address_loop:            mov ecx,[ebp+_p_dwHintName]    // dwHintName            mov edx,[ecx]            // image_thunk_data.Ordinal            test edx,edx            jz _it_fixup_next_module            test edx,080000000h      // .IF( import by ordinal )            jz _it_fixup_by_name                and edx,07FFFFFFFh    // get ordinal                jmp _it_fixup_get_addr_it_fixup_by_name:            add edx,esi  // image_thunk_data.Ordinal                         // + dwImageBase = OrdinalName            inc edx            inc edx                  // OrdinalName.Name_it_fixup_get_addr:            push edx //lpProcName            push edi                 // hModule            mov eax,offset _p_GetProcAddress            call [ebp+eax]    // GetProcAddress(hModule, lpProcName);            mov ecx,[ebp+_p_dwThunk]    // dwThunk            mov [ecx],eax  // correction the thunk            // dwThunk => next dwThunk            add dword ptr [ebp+_p_dwThunk], 004h            // dwHintName => next dwHintName            add dword ptr [ebp+_p_dwHintName],004h        jmp _it_fixup_get_proc_address_loop_it_fixup_next_module:        add ebx,014h      // sizeof(IMAGE_IMPORT_DESCRIPTOR)    jmp _it_fixup_get_lib_address_loop_it_fixup_end:    ...

    7 Support DLL and OCX

    Now, you intend to include the dynamic link library (DLL) and OLE-ActiveX Control in your PE builder project. Supporting them is very easy if you pay attention to the two-time arrival into the Offset of Entry Point, the relocation table implementation, and the client import table.

    PE Maker: Step 4

      LoadLibrary(), or an OCX is registered by using LoadLibrary() and GetProcAddress() through calling DllRegisterServer(), the first of the OEP arrival is done.  
    hinstDLL = LoadLibrary( "test1.dll" );hinstOCX = LoadLibrary( "test1.ocx" );_DllRegisterServer = GetProcAddress( hinstOCX,                                     "DllRegisterServer" );_DllRegisterServer();    // ocx register

    Download the pemaker4.zip source files from the end of the article.

    7.1 Twice OEP approach

    The Offset of Entry Point of a DLL file or an OCX file is touched by the main program atleast twice:

    • Constructor: When a DLL is loaded by
    • Destructor: When the main program frees the library usage by FreeLibrary(), the second OEP arrival happens.

       

      FreeLibrary( hinstDLL );FreeLibrary( hinstOCX );

    To perform this, I have employed a trick that causes in the second time again, the instruction pointer (EIP) traveling towards the original OEP by the structured exception handler.

    _main_0:    pushad    // save the registers context in stack    call _main_1_main_1:    pop ebp    sub ebp,offset _main_1    // get base ebp    //---------------- support dll, ocx  -----------------_support_dll_0:    jmp _support_dll_1        // nop; nop;    // << trick                              // in the second time OEP    jmp _support_dll_2_support_dll_1:    //----------------------------------------------------    ...    //---------------- support dll, ocx  1 ---------------    mov edi,[ebp+_p_dwImageBase]    add edi,[edi+03Ch]            // edi -> IMAGE_NT_HEADERS    mov ax,word ptr [edi+016h]    // edi -> image_nt_headers->                                  // FileHeader.Characteristics    test ax,IMAGE_FILE_DLL    jz _support_dll_2        mov ax, 9090h // << trick        mov word ptr [ebp+_support_dll_0],ax_support_dll_2:    //----------------------------------------------------    ...    into OEP by SEH ...

    I hope you caught the trick in the preceding code, but this is not all of it. You have a problem in ImageBase, when the library has been loaded in different image bases by the main program. You should write some code to find the real image base and store it to use forward.

        mov eax,[esp+24h]    // the real imagebase    mov ebx,[esp+30h]    // oep    cmp eax,ebx    ja _no_dll_pe_file_0        cmp word ptr [eax],IMAGE_DOS_SIGNATURE        jne _no_dll_pe_file_0            mov [ebp+_p_dwImageBase],eax_no_dll_pe_file_0:

    This code finds the real image base by investigating the stack information. By using the real image base and the formal image base, you should correct all memory calls inside the image program!! Don't be afraid; it will be done simply by the relocating the table information.

    7.2 Implement relocation table

    To understand the relocation table better, you can take a look at Section 6.6 of the Microsoft Portable Executable and Common Object File Format Specification document. The relocation table contains many packages to relocate the information related to the virtual address inside the virtual memory image. Each package is comprised of an 8-byte header to exhibit the base virtual address and the number of data, demonstrated by the IMAGE_BASE_RELOCATION data structure.

    typedef struct _IMAGE_BASE_RELOCATION {   DWORD   VirtualAddress;   DWORD   SizeOfBlock;} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION;

    Table 7 - The Relocation Table

    Block[1] VirtualAddress
    SizeOfBlock
    type:4 offset:12 type:4 offset:12
    type:4 offset:12 type:4 offset:12
    type:4 offset:12 type:4 offset:12
    ... ... ... ...
    type:4 offset:12 00 00
    Block[2] VirtualAddress
    SizeOfBlock
    type:4 offset:12 type:4 offset:12
    type:4 offset:12 type:4 offset:12
    type:4 offset:12 type:4 offset:12
    ... ... ... ...
    type:4 offset:12 00 00
    ...

     

    ...

     

    Block[n] VirtualAddress
    SizeOfBlock
    type:4 offset:12 type:4 offset:12
    type:4 offset:12 type:4 offset:12
    type:4 offset:12 type:4 offset:12
    ... ... ... ...
    type:4 offset:12 00 00

    Table 7 illustrates the main idea of the relocation table. Furthermore, you can upload a DLL or an OCX file in OllyDbg to observe the relocation table, the ".reloc" section through Memory map window. By the way, you find the position of the relocation table by using the following code in your project:

    DWORD dwVirtualAddress = image_nt_headers->  OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].  VirtualAddress;DWORD dwSize = image_nt_headers->  OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;

    By OllyDbg, you have the same as the following for the ".reloc" section, by using the Long Hex viewer mode. In this example, the base virtual address is 0x1000 and the size of the block is 0x184.

    008E1000 : 00001000  00000184  30163000  30403028008E1010 : 30683054  308C3080  30AC309C  30D830CC008E1020 : 30E030DC  30E830E4  30F030EC  310030F4008E1030 : 3120310D  315F3150  31A431A0  31C031A8008E1040 : 31D031CC  31F431EC  31FC31F8  32043200008E1050 : 320C3208  32143210  324C322C  32583254008E1060 : 3260325C  32683264  3270326C  32B03274

    It relocates the data in the subsequent virtual addresses:

    0x1000 + 0x0000 = 0x10000x1000 + 0x0016 = 0x10160x1000 + 0x0028 = 0x10280x1000 + 0x0040 = 0x10400x1000 + 0x0054 = 0x1054...

    Each package performs the relocation by using consecutive 4 bytes form its internal information. The first byte refers to the type of relocation and the next three bytes are the offset that must be used with the base virtual address and the image base to correct the image information.

    type offset
    03 00 00 00

    What is the type?

    The type can be one of the following values:

    • IMAGE_REL_BASED_ABSOLUTE (0): No effect
    • IMAGE_REL_BASED_HIGH (1): Relocate by the high 16 bytes of the base virtual address and the offset
    • IMAGE_REL_BASED_LOW (2): Relocate by the low 16 bytes of the base virtual address and the offset
    • IMAGE_REL_BASED_HIGHLOW (3): Relocate by the base virtual address and the offset

    What is done in the relocation?

    By relocation, some values inside the virtual memory are corrected according to the current image base by the ".reloc" section packages.

    delta_ImageBase = current_ImageBase - image_nt_headers->OptionalHeader.ImageBase
    mem[ current_ImageBase + 0x1000 ] =   mem[ current_ImageBase + 0x1000 ] + delta_ImageBase ;mem[ current_ImageBase + 0x1016 ] =   mem[ current_ImageBase + 0x1016 ] + delta_ImageBase ;mem[ current_ImageBase + 0x1028 ] =   mem[ current_ImageBase + 0x1028 ] + delta_ImageBase ;mem[ current_ImageBase + 0x1040 ] =   mem[ current_ImageBase + 0x1040 ] + delta_ImageBase ;mem[ current_ImageBase + 0x1054 ] =  mem[ current_ImageBase + 0x1054 ] + delta_ImageBase ;...

    I have employed the following code from Morphine packer to implement the relocation.

        ..._reloc_fixup:    mov eax,[ebp+_p_dwImageBase]    mov edx,eax    mov ebx,eax    add ebx,[ebx+3Ch]    // edi -> IMAGE_NT_HEADERS    // edx ->image_nt_headers->OptionalHeader.ImageBase    mov ebx,[ebx+034h]    sub edx,ebx // edx -> reloc_correction    // delta_ImageBase    je _reloc_fixup_end    mov ebx,[ebp+_p_dwRelocationVirtualAddress]    test ebx,ebx    jz _reloc_fixup_end    add ebx,eax_reloc_fixup_block:    mov eax,[ebx+004h]          //ImageBaseRelocation.SizeOfBlock    test eax,eax    jz _reloc_fixup_end    lea ecx,[eax-008h]    shr ecx,001h    lea edi,[ebx+008h]_reloc_fixup_do_entry:        movzx eax,word ptr [edi]//Entry        push edx        mov edx,eax        shr eax,00Ch            //Type = Entry >> 12        mov esi,[ebp+_p_dwImageBase]//ImageBase        and dx,00FFFh        add esi,[ebx]        add esi,edx        pop edx_reloc_fixup_HIGH:              // IMAGE_REL_BASED_HIGH        dec eax        jnz _reloc_fixup_LOW            mov eax,edx            shr eax,010h        //HIWORD(Delta)            jmp _reloc_fixup_LOW_fixup_reloc_fixup_LOW:               // IMAGE_REL_BASED_LOW            dec eax        jnz _reloc_fixup_HIGHLOW        movzx eax,dx            //LOWORD(Delta)_reloc_fixup_LOW_fixup:            add word ptr [esi],ax// mem[x] = mem[x] + delta_ImageBase        jmp _reloc_fixup_next_entry_reloc_fixup_HIGHLOW:           // IMAGE_REL_BASED_HIGHLOW            dec eax        jnz _reloc_fixup_next_entry        add [esi],edx           // mem[x] = mem[x] + delta_ImageBase_reloc_fixup_next_entry:        inc edi        inc edi                 //Entry++        loop _reloc_fixup_do_entry_reloc_fixup_next_base:    add ebx,[ebx+004h]    jmp _reloc_fixup_block_reloc_fixup_end:    ...

    7.3 Build a special import table

    To support the OLE-ActiveX Control registration, you should present an appropriate import table to your target OCX and DLL file. Therefore, I have established an import table by the following string:

    const char *sz_IT_OCX_strings[]={   "Kernel32.dll",   "LoadLibraryA",   "GetProcAddress",   "GetModuleHandleA",   0,   "User32.dll",   "GetKeyboardType",   "WindowFromPoint",   0,   "AdvApi32.dll",   "RegQueryValueExA",   "RegSetValueExA",   "StartServiceA",   0,   "Oleaut32.dll",   "SysFreeString",   "CreateErrorInfo",   "SafeArrayPtrOfIndex",   0,   "Gdi32.dll",   "UnrealizeObject",   0,   "Ole32.dll",   "CreateStreamOnHGlobal",   "IsEqualGUID",   0,   "ComCtl32.dll",   "ImageList_SetIconSize",   0,   0,};

    Without these API functions, the library can not be loaded, and moreover the DllregisterServer() and DllUregisterServer() will not operate. In CPECryptor::CryptFile, I have distinguished between EXE files and DLL files in the initialization of the new import table object during creation:

    if(( image_nt_headers->FileHeader.Characteristics             & IMAGE_FILE_DLL ) == IMAGE_FILE_DLL ){    ImportTableMaker = new CITMaker( IMPORT_TABLE_OCX );}else{    ImportTableMaker = new CITMaker( IMPORT_TABLE_EXE );}

     

    8 Preserve the Thread Local Storage

    By using Thread Local Storage (TLS), a program is able to execute a multithreaded process, This performance mostly is used by Borland linkers: Delphi and C++ Builder. When you pack a PE file, you should take care to keep the TLS clean; otherwise, your packer will not support Borland Delphi and C++ Builder linked EXE files. To comprehend TLS, I refer you to Section 6.7 of the Microsoft Portable Executable and Common Object File Format Specification document. You can observe the TLS structure by IMAGE_TLS_DIRECTORY32 in winnt.h.

    typedef struct _IMAGE_TLS_DIRECTORY32 {   DWORD   StartAddressOfRawData;   DWORD   EndAddressOfRawData;   DWORD   AddressOfIndex;   DWORD   AddressOfCallBacks;   DWORD   SizeOfZeroFill;   DWORD   Characteristics;} IMAGE_TLS_DIRECTORY32, * PIMAGE_TLS_DIRECTORY32;

    MessageBox() from user32.dll.

    To keep the TLS directory safe, I have copied it in a special place inside the loader:

    ..._tls_dwStartAddressOfRawData:   dword_type(0xCCCCCCCC)_tls_dwEndAddressOfRawData:     dword_type(0xCCCCCCCC)_tls_dwAddressOfIndex:          dword_type(0xCCCCCCCC)_tls_dwAddressOfCallBacks:      dword_type(0xCCCCCCCC)_tls_dwSizeOfZeroFill:          dword_type(0xCCCCCCCC)_tls_dwCharacteristics:         dword_type(0xCCCCCCCC)...

    It is necessary to correct the TLS directory entry in the Optional Header:

    if(image_nt_headers->   OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].   VirtualAddress!=0){   memcpy(&pDataTable->image_tls_directory,          image_tls_directory,          sizeof(IMAGE_TLS_DIRECTORY32));   dwOffset=DWORD(pData1)-DWORD(pNewSection);   dwOffset+=sizeof(t_DATA_1)-sizeof(IMAGE_TLS_DIRECTORY32);   image_nt_headers->      OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].      VirtualAddress=dwVirtualAddress + dwOffset;}

    9 Inject Your Code

    You are ready to place your code inside the new section. Your code is a "Hello World!" message by

    ...push MB_OK | MB_ICONINFORMATIONlea eax,[ebp+_p_szCaption]push eaxlea eax,[ebp+_p_szText]push eaxpush NULLcall _jmp_MessageBox// MessageBox(NULL, szText, szCaption, MB_OK | MB_ICONINFORMATION) ;...

    PE Maker: Step 5

    Download the pemaker5.zip source files from the end of the article.

    10 Conclusion

    By reading this article, you have perceived how easily you can inject code to a portable executable file. You can complete the code by using the source of other packers, create a packer in the same way as Yoda's Protector, and make your packer undetectable by mixing up with Morphine source code. I hope that you have enjoyed this brief discussion of one part of the reverse engineering field. See you again in the next discussion!

     

    EXCEPTION_POINTERS, you have access to the pointer of ContextRecord. The ContextRecord has the CONTEXT data structure, as seen in Table 4. This is the thread context during the exception time. When you ignore the exception by EXCEPTION_CONTINUE_SEARCH (0), the instruction pointer, as well as the context, will be set to ContextRecord to return to the previous condition. Therefore, if you change the Eip of the Win32 Thread Context to the Original Offset of Entry Point, it will come clearly into OEP.Full Size Image)

    0

    Armadillo标准壳完全扫盲


    转至: http://hi.baidu.com/%CC%EC%CD%E2%C3%AB%B3%E6/blog

    【前言】
    本人初学脱壳,以前只会用自动脱壳器,手动只脱过upx的壳,实在是菜鸟一个。日前有幸拿到一个共享软件,用peid一查,Armadillo 1.xx – 2.xx -> Silicon Realms Toolworks [Overlay],俺出生牛犊不怕虎,见壳就有脱的冲动,用od载入一看,傻了眼,这壳和upx的完全不同,入口点和一般程序差不多嘛。遂知道自己水平不济,驱猫上看雪拜读各位前辈的文章。无奈本人水平实在有限,看了大半天还是没理清楚过程。想起马gg曾经说过,实践是检验真理的唯一标准,于是操起工具对该软件大卸七块。经过2天的仔细研习,终于悟得精要,成功把壳干掉了。鉴于感觉入门门槛确实有点高,因此特写此文以帮助菜鸟们迈过刀山火海,飞向光明之巅:D

    【术语解释】
    为什么我要写这一段呢?因为我发现看高手们的脱文,最难逾越的一关是术语。高手们脱文中的各种说法,并不能马上就明白过来究竟是什么东西。因此,希望在这里把Armadillo脱文经常遇到的几个术语稍作解释。本人水平有限,如果解释有误请指出。

    [OEP] 这个是Original Entry Point的缩写,中文字面意思就是程序的原入口地址。为什么叫“原”呢?通常加壳软件会把原来的程序编码存放,以防止静态反汇编分析,并在执行前先运行一段解码的程序。所以,加壳后的程序,其入口地址是直接指向解码部分的代码,而非原来的程序入口。我们脱壳所要做的工作,就是还原出原来的程序,并且每次执行时直接从原入口地址开始执行(而不需要再运行用于解码的“壳”),因此需要得知原入口地址是什么,即OEP。

    [Armadillo] 传说中的猛壳,因为拼写太长,也有人缩写为arm壳。它使用多种加密手段以防止脱壳,比如检测debugger、修改IAT、还有高级版本的stolen byte和双线程解码。

    [IAT] Import Address Table的缩写,也有叫输入表,引入表。它用来保存程序用到的API函数的入口地址。

    [RVA] Relative Virtual Address,相对虚拟地址。win32系统会把进程读入到内存中执行,所以存在着内存地址和文件偏移的转换关系。PE文件头里面会有一个内存基址base,原来在文件中偏移为x的内容,在内存里面的偏移就变成base+x。为了区分这两种地址偏移,通常叫文件中的偏移为RVA

    [magic jump](一般破文是按10多次或者20多次F9,就来到magicjump。我根本不知道怎么去判断一个新软件的magicjump在哪里,也不知道那个次数是怎么得来的,不怕,下面我会教一种我认为比较好的方法)其实所谓magic jump,是指跳过改写IAT的代码段。Armadillo的解壳过程有一个特点,就是会改写IAT。(这里我用的是“改写”而不是某些文章中的“破坏”是有原因的。曾经我在这里也困惑过,破坏带有不可恢复的意思,事实上IAT对应的地址并没有完全破坏,只是被改写成更难辨认的形式。这里举一个具体例子)

    00E6E0E1     mov edx,[EA01B8]     // ~= kernel32.dll/00D4/FindNextFileA
    00E6E0E7     add edx,64
    00E6E0EA     call edx
    00E6E0EC     mov edx,[EA0144]     // ~= kernel32.dll/016F/GetModuleFileNameW
    00E6E0F2     add edx,64
    00E6E0F5     mov ecx,5

    这个是被改写后的IAT指向的一端程序段。里面实际工作是作还原工作。先取出edx(这里对应一个假API),然后加上64偏移才得到真正的API,再进行函数调用。FindNextFileA后面的偏移64是GetTickCount,GetModuleFileNameW后面是GetModuleHandleA,所以上面的代码相当于
    call kernel32.GetTickCount
    nop

    call kernel32.GetModuleHandleA

    这样可以使得手动脱壳过程中把IAT表弄坏(因为无法识别出正确的API),但是加壳程序却可以正常运行。是不是很狡猾?解决办法也简单,在脱壳的过程中避开执行改写IAT表的代码段,只需要修改一条指令,这条指令,正是magic jump!

    能够坚持看到这里是否已经有点烦闷了?基本理论就这么多了。准备好工具了吗?让我们马上开始。

    【工具】OD、LordPE、ImportREC
    【过程】
    【Action 1】 明察暗访OEP
    OD载入程序,用插件隐藏OD,忽略所有异常,alt_m查看内存映射,在00401000处下内存读取断点,F9
    程序停下来了,看到没有,熟悉的开头。没有看到?肯定你遇到异常了,shift_F9试试?
    005E14E4      55               push ebp
    005E14E5      8BEC             mov ebp,esp
    005E14E7      83C4 E4          add esp,-1C

    我们找到OEP了,马上记下吧。Action 1目标完成:OEP=001E14E4
    等等,是不是打错字了?不是005E14E4吗?还记得RVA吗?通常来说,windows会把程序读到从00400000开始的连续内存空间(当然也不是一成不变,只是通常碰到的情况都是这样),也就是说你看到的OEP 005E14E4是内存的地址,它的RVA是001E14E4。明白了吗?

    【Action 2】攻下桥头堡
    运行到OEP预示着解码阶段的完成了。所以理论上现在内存中的是已解码的程序。先不要动OD,保持在OEP入口。运行LordPE,选刚刚运行的程序的线程,full dump,Action 2完成!

    先别对着dump出来的exe笑啊,如果现在那个是最终的脱壳结果,Armadillo就不叫猛壳了,我刚刚写的一堆理论也就白费劲。喝口水再继续吧。下面才到重点。

    【Action 3】扫清地雷阵
    OD没有关掉吧?恩,别动它,继续保持。运行ImportREC,选择程序进程,在下面的IAT Infos needed填入刚才拿到的OEP。AutoSearch,看到RVA框变了,那个就是IAT的地址和大小了。我这里找到的数值是001ED240
    回到OD,d 5ed240(还记得刚刚说过的内存偏移的换算关系吗?),看到什么了?那个就是IAT呀。记下它的样子。然后分别在第一个项目和最后一个项目下硬件写入断点。(为什么用硬件捏?因为它不影响速度,而且重新运行的时候不会没掉,呵呵)
    下面重新运行吧。F9,碰到硬件断点了。还记得IAT的样子吗?继续F9,直到第一个条目和你刚刚记下的一样。现在按page up,一直向上找GetModuleHandleA

    00E86AB1      6A 00            push 0
    00E86AB3      FF15 D400E900    call dword ptr ds:[E900D4]                ; kernel32.GetModuleHandleA
    00E86AB9      3985 90C4FFFF    cmp dword ptr ss:[ebp-3B70],eax
    00E86ABF      75 0F            jnz short 00E86AD0
    00E86AC1      C785 8CC4FFFF 8>mov dword ptr ss:[ebp-3B74],0E95180
    00E86ACB      E9 C4000000      jmp 00E86B94
    00E86AD0      83A5 68C2FFFF 0>and dword ptr ss:[ebp-3D98],0
    00E86AD7      C785 64C2FFFF C>mov dword ptr ss:[ebp-3D9C],0E957C0
    00E86AE1      EB 1C            jmp short 00E86AFF
    00E86AE3      8B85 64C2FFFF    mov eax,dword ptr ss:[ebp-3D9C]
    00E86AE9      83C0 0C          add eax,0C
    00E86AEC      8985 64C2FFFF    mov dword ptr ss:[ebp-3D9C],eax
    00E86AF2      8B85 68C2FFFF    mov eax,dword ptr ss:[ebp-3D98]
    00E86AF8      40               inc eax
    00E86AF9      8985 68C2FFFF    mov dword ptr ss:[ebp-3D98],eax
    00E86AFF      8B85 64C2FFFF    mov eax,dword ptr ss:[ebp-3D9C]
    00E86B05      8338 00          cmp dword ptr ds:[eax],0
    00E86B08      0F84 86000000    je 00E86B94
    00E86B0E      8B85 64C2FFFF    mov eax,dword ptr ss:[ebp-3D9C]
    00E86B14      8B40 08          mov eax,dword ptr ds:[eax+8]
    00E86B17      83E0 01          and eax,1
    00E86B1A      85C0             test eax,eax
    00E86B1C      74 25            je short 00E86B43
    00E86B1E      A1 2800EA00      mov eax,dword ptr ds:[EA0028]
    00E86B23      8B0D 2800EA00    mov ecx,dword ptr ds:[EA0028]
    00E86B29      8B40 20          mov eax,dword ptr ds:[eax+20]
    00E86B2C      3341 40          xor eax,dword ptr ds:[ecx+40]
    00E86B2F      8B0D 2800EA00    mov ecx,dword ptr ds:[EA0028]
    00E86B35      3341 28          xor eax,dword ptr ds:[ecx+28]
    00E86B38      25 80000000      and eax,80
    00E86B3D      85C0             test eax,eax
    00E86B3F      74 02            je short 00E86B43
    00E86B41    ^ EB A0            jmp short 00E86AE3
    00E86B43      8B85 68C2FFFF    mov eax,dword ptr ss:[ebp-3D98]
    00E86B49      8B0D 74B7E900    mov ecx,dword ptr ds:[E9B774]
    00E86B4F      8B15 2800EA00    mov edx,dword ptr ds:[EA0028]
    00E86B55      8B0481           mov eax,dword ptr ds:[ecx+eax*4]
    00E86B58      3342 24          xor eax,dword ptr ds:[edx+24]
    00E86B5B      8B0D 2800EA00    mov ecx,dword ptr ds:[EA0028]
    00E86B61      3341 28          xor eax,dword ptr ds:[ecx+28]
    00E86B64      8B0D 2800EA00    mov ecx,dword ptr ds:[EA0028]
    00E86B6A      3341 44          xor eax,dword ptr ds:[ecx+44]
    00E86B6D      8B0D 2800EA00    mov ecx,dword ptr ds:[EA0028]
    00E86B73      3341 6C          xor eax,dword ptr ds:[ecx+6C]
    00E86B76      3985 90C4FFFF    cmp dword ptr ss:[ebp-3B70],eax

    你看到的这段可能会跟我给出的有点差异,不过很好认,会有一段mov和xor交错出现的地方,并且mov语句是完全相同的。这里是00E86B1E-00E86B76

    向上找可以跳过这段代码的转跳语句,这里是
    00E86B08      0F84 86000000    je 00E86B94     ;magic jump!!!!!!!!

    我看到其他教程,这句是je short的,所以可能是Armadillo版本不同。不过道理都是一样,避开对IAT表的改写。
    把这句改成jmp,再按F9,遇到第二个硬件断点,这时IAT转换完成。这个可是没有被做过手脚的完整IAT啊~
    哦,这里别忘了,回到刚刚修改的jmp那里,改回je啊。不然后面的解码会出错导致程序异常终止了。(至少我脱的这个壳会这样。好像只有很少的脱文提到要恢复指令,反正恢复也没坏,多做一步吧,不然异常了可能还要重新来过)
    再bp 005e14e4,在OEP处下断,F9,运行到OEP

    【Action 4】长驱直入,胜利会师
    拿出ImportREC出来吧,重新选一下进程,autosearch,步骤应该都熟悉了。这次可以点Get Imports了。如果还有unresolved pointer,就点Show Invalid,Trace Level1试试,剩下的用Cut thunk全部干掉。然后fix dump,选择Action 2 dump出来的exe,应该就多出来一个文件名后面多带一个_的exe文件。这个是脱壳后独立运行的exe啊。试试能不能运行,不行的话,调整一下ImportREC的参数再试试,有些软件不能用Add new section的。把auto search的结果填到New Import Infos,去掉Add new section再试一遍。

    【Action 5】清除残余势力
    脱壳出来的程序很大,因为里面包含了很多已经没用的解码程序段。为了做到完美脱壳,我们可以把没用的代码清理掉。主要过程可以参考《脱壳后软件减肥大法》http://www.pediy.com/bbshtml/BBS6/pediy6313.htm,这里就不赘述了。不过调整.idata保证VA连续的那一步我不是按它的,不需要手动调整,直接用LordPE的rebuild PE就可以了,有现成工具干吗还要造轮子了?

    【后记】
    当我看到脱壳出来的程序正常运行时,有一种兴奋的感觉。也许我是脱壳菜鸟,这些对高手们确实不值得一提。可是正如fly斑竹所说,我知道自己进阶了。把过程和大家共享,希望大家可以跨过入门的门槛,共同进步。

    0

    修改PE文件结构


    转至http://www.xfocus.net

    在windows 9x、NT、2000下,所有的可执行文件都是基于Microsoft设计的一种新的文件格式Portable Executable File Format(可移植的执行体),即PE格式。有一些时候,我们需要对这些可执行文件进行修改,下面文字试图详细的描述PE文件的格式及对PE格式文件的修改。
    1、PE文件框架构成
    DOS MZ header
    DOS stub
    PE header
    Section table
    Section 1
    Section 2
    Section …
    Section n
    上表是PE文件结构的总体层次分布。所有 PE文件(甚至32位的 DLLs) 必须以一个简单的 DOS MZ header 开始,在偏移0处有DOS下可执行文件的“MZ标志”,有了它,一旦程序在DOS下执行,DOS就能识别出这是有效的执行体,然后运行紧随 MZ header 之后的 DOS stub。DOS stub实际上是个有效的EXE,在不支持 PE文件格式的操作系统中,它将简单显示一个错误提示,类似于字符串 " This program cannot run in DOS mode " 或者程序员可根据自己的意图实现完整的 DOS代码。通常DOS stub由汇编器/编译器自动生成,对我们的用处不是很大,它简单调用中断21h服务9来显示字符串"This program cannot run in DOS mode"。
    紧接着 DOS stub 的是 PE header。 PE header 是PE相关结构 IMAGE_NT_HEADERS 的简称,其中包含了许多PE装载器用到的重要域。可执行文件在支持PE文件结构的操作系统中执行时,PE装载器将从 DOS MZ header的偏移3CH处找到 PE header 的起始偏移量。因而跳过了 DOS stub 直接定位到真正的文件头 PE header。
    PE文件的真正内容划分成块,称之为sections(节)。每节是一块拥有共同属性的数据,比如“.text”节等,那么,每一节的内容都是什么呢?实际上PE格式的文件把具有相同属性的内容放入同一个节中,而不必关心类似“.text”、“.data”的命名,其命名只是为了便于识别,所有,我们如果对PE格式的文件进行修改,理论上讲可以写入任何一个节内,并调整此节的属性就可以了。
    PE header 接下来的数组结构 section table(节表)。 每个结构包含对应节的属性、文件偏移量、虚拟偏移量等。如果PE文件里有5个节,那么此结构数组内就有5个成员。
    以上就是PE文件格式的物理分布,下面将总结一下装载一PE文件的主要步骤:
    1、    PE文件被执行,PE装载器检查 DOS MZ header 里的 PE header 偏移量。如果找到,则跳转到 PE header。
    2、PE装载器检查 PE header 的有效性。如果有效,就跳转到PE header的尾部。
    3、紧跟 PE header 的是节表。PE装载器读取其中的节信息,并采用文件映射方法将这些节映射到内存,同时付上节表里指定的节属性。
    4、PE文件映射入内存后,PE装载器将处理PE文件中类似 import table(引入表)逻辑部分。
    上述步骤是一些前辈分析的结果简述。
    2、PE文件头概述
    我们可以在winnt.h这个文件中找到关于PE文件头的定义:
    typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;                
    //PE文件头标志 :“PE\0\0”。在开始DOS header的偏移3CH处所指向的地址开始
    IMAGE_FILE_HEADER FileHeader;        //PE文件物理分布的信息
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;    //PE文件逻辑分布的信息
    } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

    typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;            //该文件运行所需要的CPU,对于Intel平台是14Ch
    WORD    NumberOfSections;        //文件的节数目
    DWORD   TimeDateStamp;        //文件创建日期和时间
    DWORD   PointerToSymbolTable;    //用于调试
    DWORD   NumberOfSymbols;        //符号表中符号个数
    WORD    SizeOfOptionalHeader;    //OptionalHeader 结构大小
    WORD    Characteristics;        //文件信息标记,区分文件是exe还是dll
    } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

    typedef struct _IMAGE_OPTIONAL_HEADER {
    WORD    Magic;            //标志字(总是010bh)
    BYTE    MajorLinkerVersion;        //连接器版本号
    BYTE    MinorLinkerVersion;        //
    DWORD   SizeOfCode;            //代码段大小
    DWORD   SizeOfInitializedData;    //已初始化数据块大小
    DWORD   SizeOfUninitializedData;    //未初始化数据块大小
    DWORD   AddressOfEntryPoint;    //PE装载器准备运行的PE文件的第一个指令的RVA,若要改变整个执行的流程,可以将该值指定到新的RVA,这样新RVA处的指令首先被执行。(许多文章都有介绍RVA,请去了解)
    DWORD   BaseOfCode;            //代码段起始RVA
    DWORD   BaseOfData;            //数据段起始RVA
    DWORD   ImageBase;            //PE文件的装载地址
    DWORD   SectionAlignment;        //块对齐
    DWORD   FileAlignment;        //文件块对齐
    WORD    MajorOperatingSystemVersion;//所需操作系统版本号
    WORD    MinorOperatingSystemVersion;//
    WORD    MajorImageVersion;        //用户自定义版本号
    WORD    MinorImageVersion;        //
    WORD    MajorSubsystemVersion;    //win32子系统版本。若PE文件是专门为Win32设计的
    WORD    MinorSubsystemVersion;    //该子系统版本必定是4.0否则对话框不会有3维立体感
    DWORD   Win32VersionValue;        //保留
    DWORD   SizeOfImage;            //内存中整个PE映像体的尺寸
    DWORD   SizeOfHeaders;        //所有头+节表的大小
    DWORD   CheckSum;            //校验和
    WORD    Subsystem;            //NT用来识别PE文件属于哪个子系统
    WORD    DllCharacteristics;        //
    DWORD   SizeOfStackReserve;        //
    DWORD   SizeOfStackCommit;        //
    DWORD   SizeOfHeapReserve;        //
    DWORD   SizeOfHeapCommit;        //
    DWORD   LoaderFlags;            //
    DWORD   NumberOfRvaAndSizes;    //
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
    //IMAGE_DATA_DIRECTORY 结构数组。每个结构给出一个重要数据结构的RVA,比如引入地址表等
    } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

    typedef struct _IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress;        //表的RVA地址
    DWORD   Size;                //大小
    } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

    PE文件头后是节表,在winnt.h下如下定义
    typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];//节表名称,如“.text”
    union {
        DWORD   PhysicalAddress;    //物理地址            
        DWORD   VirtualSize;        //真实长度
    } Misc;
    DWORD   VirtualAddress;        //RVA
    DWORD   SizeOfRawData;        //物理长度
    DWORD   PointerToRawData;        //节基于文件的偏移量
    DWORD   PointerToRelocations;    //重定位的偏移
    DWORD   PointerToLinenumbers;    //行号表的偏移
    WORD    NumberOfRelocations;    //重定位项数目
    WORD    NumberOfLinenumbers;    //行号表的数目
    DWORD   Characteristics;        //节属性
    } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

    以上结构就是在winnt.h中关于PE文件头的定义,如何我们用C/C++来进行PE可执行文件操作,就要用到上面的所有结构,它详细的描述了PE文件头的结构。

    3、修改PE可执行文件
    现在让我们把一段代码写入任何一个PE格式的可执行文件,代码如下:
    – test.asm –
    .386p
    .model flat, stdcall
    option casemap:none

    include \masm32\include\.inc
    include \masm32\include\user32.inc
    includelib \masm32\lib\user32.lib

    .code

    start:
        INVOKE MessageBoxA,0,0,0,MB_ICONINFORMATION or MB_OK
        ret
    end start

    以上代码只显示一个MessageBox框,编译后得到二进制代码如下:
    unsigned char writeline[18]={
    0x6a,0×40,0x6a,0×0,0x6a,0×0,0x6a,0×0,0xe8,0×01,0×0,0×0,0×0,0xe9,0×0,0×0,0×0,0×0
    };

    好,现在让我们看看该把这些代码写到那。现在用Tdump.exe显示一个PE格式得可执行文件信息,可以发现如下描述:
    Object table:
    #   Name      VirtSize    RVA     PhysSize  Phys off  Flags  
    –  ——–  ——–  ——–  ——–  ——–  ——–
    01  .text     0000CCC0  00001000  0000CE00  00000600  60000020 [CER]
    02  .data     00004628  0000E000  00002C00  0000D400  C0000040 [IRW]
    03  .rsrc     000003C8  00013000  00000400  00010000  40000040 [IR]

    Key to section flags:
      C – contains code
      E – executable
      I – contains initialized data
      R – readable
      W – writeable

    上面描述此文件中存在3个段及每个段得信息,实际上我们的代码可以写入任何一个段,这里我选择“.text”段。

    用如下代码得到一个PE格式可执行文件的头信息:

    //writePE.cpp

    #include <windows.h>
    #include <stdio.h>
    #include <io.h>
    #include <fcntl.h>
    #include <time.h>
    #include <SYS\STAT.H>

    unsigned char writeline[18]={
    0x6a,0×40,0x6a,0×0,0x6a,0×0,0x6a,0×0,0xe8,0×01,0×0,0×0,0×0,0xe9,0×0,0×0,0×0,0×0
    };

    DWORD space;
    DWORD entryaddress;
    DWORD entrywrite;
    DWORD progRAV;
    DWORD oldentryaddress;
    DWORD newentryaddress;
    DWORD codeoffset;
    DWORD peaddress;
    DWORD flagaddress;
    DWORD flags;

    DWORD virtsize;
    DWORD physaddress;
    DWORD physsize;
    DWORD MessageBoxAadaddress;

    int main(int argc,char * * argv)
    {
    HANDLE hFile, hMapping;
    void *basepointer;
    FILETIME * Createtime;
    FILETIME * Accesstime;
    FILETIME * Writetime;
    Createtime = new FILETIME;
    Accesstime = new FILETIME;
    Writetime = new FILETIME;

    if ((hFile = CreateFile(argv[1], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0)) == INVALID_HANDLE_VALUE)//打开要修改的文件
    {
    puts("(could not open)");
    return EXIT_FAILURE;
    }
    if(!GetFileTime(hFile,Createtime,Accesstime,Writetime))
    {
    printf("\nerror getfiletime: %d\n",GetLastError());
    }
    //得到要修改文件的创建、修改等时间
    if (!(hMapping = CreateFileMapping(hFile, 0, PAGE_READONLY | SEC_COMMIT, 0, 0, 0)))
    {
    puts("(mapping failed)");
    CloseHandle(hFile);
    return EXIT_FAILURE;
    }
    if (!(basepointer = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0)))
    {
    puts("(view failed)");
    CloseHandle(hMapping);
    CloseHandle(hFile);
    return EXIT_FAILURE;
    }
    //把文件头映象存入baseointer
    CloseHandle(hMapping);
    CloseHandle(hFile);
    map_exe(basepointer);//得到相关地址
    UnmapViewOfFile(basepointer);
    printaddress();
    printf("\n\n");
    if(space<50)
    {
    printf("\n空隙太小,数据不能写入.\n");
    }
    else
    {
    writefile();//写文件
    }

    if ((hFile = CreateFile(argv[1], GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0)) == INVALID_HANDLE_VALUE)
    {
    puts("(could not open)");
    return EXIT_FAILURE;
    }

    if(!SetFileTime(hFile,Createtime,Accesstime,Writetime))
    {
    printf("error settime : %d\n",GetLastError());
    }
    //恢复修改后文件的建立时间等
    delete Createtime;
    delete Accesstime;
    delete Writetime;
    CloseHandle(hFile);
    return 0;
    }

    void map_exe(const void *base)
    {
    IMAGE_DOS_HEADER * dos_head;
    dos_head =(IMAGE_DOS_HEADER *)base;
    #include <pshpack1.h>
    typedef struct PE_HEADER_MAP
    {
    DWORD signature;
    IMAGE_FILE_HEADER _head;
    IMAGE_OPTIONAL_HEADER opt_head;
    IMAGE_SECTION_HEADER section_header[];
    } peHeader;
    #include <poppack.h>

    if (dos_head->e_magic != IMAGE_DOS_SIGNATURE)
    {
    puts("unknown type of file");
    return;
    }

    peHeader * header;
    header = (peHeader *)((char *)dos_head + dos_head->e_lfanew);//得到PE文件头
    if (IsBadReadPtr(header, sizeof(*header))
    {
    puts("(no PE header, probably DOS executable)");
    return;
    }

    DWORD mods;
    char tmpstr[4]={0};
    DWORD  tmpaddress;
    DWORD  tmpaddress1;

    if(strstr((const char *)header->section_header[0].Name,".text")!=NULL)
    {
    virtsize=header->section_header[0].Misc.VirtualSize;
    //此段的真实长度
    physaddress=header->section_header[0].PointerToRawData;
    //此段的物理偏移
    physsize=header->section_header[0].SizeOfRawData;
    //此段的物理长度
    peaddress=dos_head->e_lfanew;
    //得到PE文件头的开始偏移

    peHeader peH;
    tmpaddress=(unsigned long )&peH;
    //得到结构的偏移
    tmpaddress1=(unsigned long )&(peH.section_header[0].Characteristics);
    //得到变量的偏移
    flagaddress=tmpaddress1-tmpaddress+2;
    //得到属性的相对偏移
    flags=0×8000;
    //一般情况下,“.text”段是不可读写的,如果我们要把数据写入这个段需要改变其属性,实际上这个程序并没有把数据写入“.text”段,所以并不需要更改,但如果你实现复杂的功能,肯定需要数据,肯定需要更改这个值,

    space=physsize-virtsize;
    //得到代码段的可用空间,用以判断可不可以写入我们的代码
    //用此段的物理长度减去此段的真实长度就可以得到
    progRAV=header->opt_head.ImageBase;
    //得到程序的装载地址,一般为400000
    codeoffset=header->opt_head.BaseOfCode-physaddress;
    //得到代码偏移,用代码段起始RVA减去此段的物理偏移
    //应为程序的入口计算公式是一个相对的偏移地址,计算公式为:
    //代码的写入地址+codeoffset

    entrywrite=header->section_header[0].PointerToRawData+header->section_header[0].Misc.VirtualSize;
    //代码写入的物理偏移
    mods=entrywrite%16;
    //对齐边界
    if(mods!=0)
    {
    entrywrite+=(16-mods);
    }
    oldentryaddress=header->opt_head.AddressOfEntryPoint;
    //保存旧的程序入口地址
    newentryaddress=entrywrite+codeoffset;
    //计算新的程序入口地址        
    return;
    }

    void printaddress()
    {
    HINSTANCE gLibMsg=NULL;
    DWORD funaddress;
    gLibMsg=LoadLibrary("user32.dll");
    funaddress=(DWORD)GetProcAddress(gLibMsg,"MessageBoxA");
    MessageBoxAadaddress=funaddress;
    gLibAMsg=LoadLibrary("kernel32.dll");
    //得到MessageBox在内存中的地址,以便我们使用
    }

    void writefile()
    {
    int ret;
    long retf;
    DWORD address;
    int tmp;
    unsigned char waddress[4]={0};

    ret=_open(filename,_O_RDWR | _O_CREAT | _O_BINARY,_S_IREAD | _S_IWRITE);
    if(!ret)
    {
    printf("error open\n");
    return;
    }
        
    retf=_lseek(ret,(long)peaddress+40,SEEK_SET);
    //程序的入口地址在PE文件头开始的40处
    if(retf==-1)
    {
    printf("error seek\n");
    return;
    }
    address=newentryaddress;
    tmp=address>>24;
    waddress[3]=tmp;
    tmp=address<<8;
    tmp=tmp>>24;
    waddress[2]=tmp;
    tmp=address<<16;
    tmp=tmp>>24;
    waddress[1]=tmp;
    tmp=address<<24;
    tmp=tmp>>24;
    waddress[0]=tmp;
    retf=_write(ret,waddress,4);
    //把新的入口地址写入文件
    if(retf==-1)
    {
    printf("error write: %d\n",GetLastError());
    return;
    }
        
    retf=_lseek(ret,(long)entrywrite,SEEK_SET);
    if(retf==-1)
    {
    printf("error seek\n");
    return;
    }
    retf=_write(ret,writeline,18);
    if(retf==-1)
    {
    printf("error write: %d\n",GetLastError());
    return;
    }
    //把writeline写入我们计算出的空间

    retf=_lseek(ret,(long)entrywrite+9,SEEK_SET);
    //更改MessageBox函数地址,它的二进制代码在writeline[10]处
    if(retf==-1)
    {
    printf("error seek\n");
    return;
    }

    address=MessageBoxAadaddress-(progRAV+newentryaddress+9+4);
    //重新计算MessageBox函数的地址,MessageBox函数的原地址减去程序的装载地址加上新的入口地址加9(它的二进制代码相对偏移)加上4(地址长度)
    tmp=address>>24;
    waddress[3]=tmp;
    tmp=address<<8;
    tmp=tmp>>24;
    waddress[2]=tmp;
    tmp=address<<16;
    tmp=tmp>>24;
    waddress[1]=tmp;
    tmp=address<<24;
    tmp=tmp>>24;
    waddress[0]=tmp;
    retf=_write(ret,waddress,4);
    //写入重新计算的MessageBox地址
    if(retf==-1)
    {
    printf("error write: %d\n",GetLastError());
    return;
    }

    retf=_lseek(ret,(long)entrywrite+14,SEEK_SET);
    //更改返回地址,用jpm返回原程序入口地址,其它的二进制代码在writeline[15]处
    if(retf==-1)
    {
    printf("error seek\n");
    return;
    }

    address=0-(newentryaddress-oldentryaddress+4+15);
    //返回地址计算的方法是新的入口地址减去老的入口地址加4(地址长度)加15(二进制代码相对偏移)后取反
    tmp=address>>24;
    waddress[3]=tmp;
    tmp=address<<8;
    tmp=tmp>>24;
    waddress[2]=tmp;
    tmp=address<<16;
    tmp=tmp>>24;
    waddress[1]=tmp;
    tmp=address<<24;
    tmp=tmp>>24;
    waddress[0]=tmp;
    retf=_write(ret,waddress,4);
    //写入返回地址
    if(retf==-1)
    {
    printf("error write: %d\n",GetLastError());
    return;
    }

    _close(ret);
    printf("\nall done…\n");
    return;
    }

    //end
    由于在PE格式的文件中,所有的地址都使用RVA地址,所以一些函数调用和返回地址都要经过计算才可以得到,以上是我在实践中的心得,如果你有更好的办法,真心的希望你能告诉我。

    如果存在错误,请告诉我,以免误导看这篇文章的人。
    写的较乱,请原谅。

    ilsy@netguard.com.cn

    0

    实现和IE浏览器交互的几种方法的介绍


    内容
    实现和IE浏览器交互的几种方法的介绍
    —- 1.引言

    —- 如何实现对IE浏览器中对象的操作是一个很有实际意义问题,通过和IE绑定的DLL我们可以记录IE浏览过的网页的顺序,分析用户的使用行为和模式。我们可以对网页的内容进行过滤和翻译,可以自动填写网页中经常需要用户填写的Form内容等等,我们所有的例子代码都是通过VC来表示的,采用的原理是通过和IE对象的接口的交互来实现对IE的访问。实际上是采用COM的技术,我们知道COM是和语言无关的一种二进制对象交互的模式,所以实际上我们下面所描述的内容都可以用其他的语言来实现,比如VB,DELPHI,C++ Builder等等。

    —- 2.IE实例遍历实现

    —- 首先我们来看系统是如何知道当前有多少个IE的实例在运行。

    —- 我们知道在Windows体系结构下,一个应用程序可以通过操作系统的运行对象表来和这些应用的实例进行交互。但是IE当前的实现机制是不在运行对象表中进行注册,所以需要采用其他的方法。我们知道可以通过ShellWindows集合来代表属于shell的当前打开的窗口的集合,而IE就是属于shell的一个应用程序。

    —- 下面我们描述一下用VC实现对当前 IE实例的进行遍历的方法。IShellWindows是关于系统shell的一个接口,我们可以定义一个如下的接口变量:

    SHDocVw::IShellWindowsPtr m_spSHWinds;
    然后创建变量的实例:
       m_spSHWinds.CreateInstance
       (__uuidof(SHDocVw::ShellWindows));
    通过IShellWindows接口的方法GetCount
    可以得到当前实例的数目:
          long nCount = m_spSHWinds- >GetCount();
    通过IShellWindows接口的方法Item
    可以得到每一个实例对象
        IDispatchPtr spDisp;
        _variant_t va(i, VT_I4);
        spDisp = m_spSHWinds->Item(va);
    然后我们可以判断实例对象是不是
    属于IE浏览器对象,通过下面的语句实现:
        SHDocVw::IWebBrowser2Ptr spBrowser(spDisp);
        assert(spBrowser != NULL)

    —-在得到了IE浏览器对象以后,我们可以调用IWebBrowser2Ptr接口的方法来得到当前的文档对象的指针: MSHTML::IHTMLDocument2Ptr spDoc(spBrowser->GetDocument());

    —- 然后我们就可以通过这个接口对这个文档对象进行操作,比如通过Gettitle得到文档的标题。

    —- 我们在浏览网络的时候,一般总会同时开很多IE的实例,如果这些页面都是很好的话,我们可能想保存在硬盘上,这样,我们需要对每一个实例进行保存,而如果我们采用上面的原理,我们可以得到每一个IE的实例及其网页对象的接口,这样就可以通过一个简单的程序来批量的保存当前的所有打开的网页。采用上面介绍的方法实现了对当前IE实例的遍历,但是我们希望得到每一个IE实例所产生的事件,这就需要通过DLL的机制来实现。

    —- 3.和IE相绑定的DLL的实现

    —- 我们介绍一下如何建立和IE进行绑定的DLL的实现的过程。为了和IE的运行实例进行绑定,我们需要建立一个能够和每一个IE实例进行绑定的DLL。IE的启动过程是这样的,当每一个IE的实例启动的时候,它都会在注册表中去寻找这个的一个CLSID,具体的注册表的键位置为:

    HKEY_LOCALL_MACHINESOFTWAREMicrosoftWindows
    CurrentVersionExplorerBrowser Helper Objects

    —- 当在这个键位置下存在CLSIDs的时候,IE会通过使用CoCreateInstance()方法来创建列在该键位置下的每一个对象的实例。注意对象的CLSIDs必须用子键而非启动过程是这样的,当每一个IE的实例启动的时候名字值的形式表现,比如{DD41D66E-CE4F-11D2-8DA9-00A0249EABF4} 就是一个有效的子键。我们使用DLL的形式而非EXE的形式的原因是因为DLL和IE实例运行在同一个进程空间里面。每一个这种形式的DLL必须实现接口IObjectWithSite,其中方法SetSite必须被实现。通过这个方法,我们自己的DLL就可以得到一个指向IE COM对象的IUnknown的指针,实际上通过这个指针我们就可以通过COM对象中的方法QueryInterface来遍历所有可以得到的接口,这是COM的基本的机制。当然我们需要的只是IWebBrowser2这个接口。

    —- 实际上我们建立的是一个COM对象,DLL只不过是COM对象的一种表现形式。我们建立的COM对象需要建立和实现的方法有:

    —-1. IOleObjectWithSite接口的方法SetSite必须实现。实际上IE实例通过这个方法向我们的COM对象传递一个接口的指针。假设我们有一个接口指针的变量,不妨设为:

    —-CComQIPtr< IWebBrowser2, &IID_IWebBrowser2 > m_myWebBrowser2;

    —- 我们就可以在方法SetSite中把这个传进来的接口指针赋给m_myWebBrowser2。 2. 在我们得到了指向IE COM对象的接口后,我们需要把自己的DLL和IE实例所发生的事件相关连,为了实现这个目的,需要介绍两个接口:

    —-(1) IConnectionPointContainer。:

    —-CComQIPtr< IWebBrowser2, &这里使用这个接口的目的是用来根据它得到的IID来建立和DLL的一个特定的连接。比如我们可以进行如下的定义:

    CComQIPtr< IConnectionPointContainer,
    &IID_IConnectionPointContainer >          
    spCPContainer(m_myWebBrowser2);

    —-然后,我们需要把所有IE中发生的事件和我们的DLL进行通讯,可以使用 IConnectPoint。

    —-(2) IConnectPoint。通过这个接口,客户可以对连接的对象开始或者是终止一个advisory循环。IConnectPoint有两个主要的方法,一个为Advice,另一个为Unadvise。对于我们的应用来说,Advise是用来在每一个IE发生的事件和DLL之间建立一个通道。而Unadvise就是用来终止以前用Advise建立的通知关系。比如我们可以定义IConnectPoint接口如下: CComPtr< IConnectionPoint > spConnectionPoint;

    —- 然后,我们要使所有在IE实例中发生的事件和我们的DLL相关,可以使用 如下的方法:

    hr = spCPContainer->FindConnectionPoint(
    DIID_DWebBrowserEvents2, &spConnectionPoint);

    —-然后我们通过IConnectPoint接口的方法Advice使每当IE有一个新的事件发生的时候,都能够让我们的DLL知道。可以用如下的语句实现:

    hr = spConnectionPoint- >Advise(
    (IDispatch*)this, &m_dwIDCode);

    —-在把IE实例中的事件和我们的DLL之间建立联系以后,我们可以通过IDispatch接口的Invoke()方法来处理所有的IE的事件。

    —-3. IDispatch接口的Invoke()方法。IDispatch是从IUnknown中继承的一个接口的类型,通过COM接口提供的任何服务都可以通过IDispatch接口来实现。IDispatch::Invoke的工作方式同vtbl幕后的工作方式是类似的,Invoke将实现一组按索引来访问的函数,我们可以对Invoke方法进行动态的定制以提供不同的服务。Invoke方法的表示如下:

    STDMETHOD(Invoke)(DISPID dispidMember,REFIID
    riid, LCID lcid, WORD wFlags,
    DISPPARAMS * pdispparams, VARIANT * pvarResult,
    EXCEPINFO * pexcepinfo, UINT * puArgErr);

    —-其中,DISPID是一个长整数,它标识的是一个函数。对于IDispatch的某一个特定的实现,DISPID都是唯一的。IDispatch的每一个实现都有其自己的IID,这里dispidMemeber实际上是可以认为是和IE实例所发生的每一个事件相关的方法,比如:DISPID_BEFORENAVIGATE2,DISPID_NAVIGATECOMPLETE2等等。 这个方法中另外一个比较重要的参数是DISPPARAMS,它的结构如下:

    typedef struct tagDISPPARAMS
       {
           VARIANTARG* rgvarg;
    //VARIANTARG是同VARAIANT相同的,可以在
        //OAIDL.IDL中找到。所以实际上rgvarg是一个参数数
         //组
           DISPID*  rgdispidNameArgs;  //命名参数的DISPID
           unsigned int cArgs;    //表示数组中元素的个数
           unsigned int CnameArgs;  //命名元素的个数
       }DISPPARAMS

    —-要注意的是每一个参数的类型都是VARIANTARG,所以在IE和我们DLL之间可以传递的参数类型的数目是有限的。只有那些能够被放到VARIANTARG结构中的类型才可以通过调度接口进行传递。 比如对于事件DISPID_NAVIGATECOMPLETE2来说:第一个参数表示IE在访问的URL的值,类型是VT_BYREF|VT_VARIANT。注意DISPID_NAVIGATECOMPLETE2等DISPID已经在VC中被定义,我们可以直接进行使用。 如上说述,我们在方法Invoke中可以得到所有IE实例所发生的事件,我们可以把这些数据放到文件中进行事后的分析,也可以放到一个列表框中实时的显示。

    —- 4.微软的HTML文档对象模型和应用分析

    —- 下面我们来看如何得到网页文档的接口:网页文档的接口为IHTMLDocument2,可以通过调用IE COM对象的get_Document方法来得到网页的接口。使用如下的语句:

    hr = m_spWebBrowser2- >get_Document(&spDisp);
    CComQIPtr< IHTMLDocument2,
    &IID_IHTMLDocument2 > spHTML;
    spHTML = spDisp;

    —- 这样我们就得到了网页对象的接口,然后我们就可以对网页进行分析,比如通过IHTMLDocument2提供的方法get_URL我们可以得到和该网页相关的URL的地址值,通过get_forms方法可以该网页中所有的Form对象的集合。实际上W3C组织已经制定了一个DOM(Document Objec Model)标准,当然这个标准不仅仅是针对HTML,同时还是针对XML制定的。W3C组织只是定义了网页对象的接口,不同的公司可以采用不同的语言和方法进行具体的实现。按照W3C组织定义的网页对象被认为是动态的,即用户可以动态的对网页对象里面所包含的每一个对象进行操作。这里的对象可以是指一个输入框,也可以是图象和声音等对象。同时按照W3C的正式文档的说明,网页对象是可以动态增加和删除的。事实上,很少有厂商实现了DOM定义的所有功能。微软对网页对象的定义也基本上是按照这个标准实现的。但是当前的接口还不支持动态的增加和删除元素,但是可以对网页中的基本元素进行属性的修改。比如IHTMLElementCollection表示网页中一些基本的元素的集合,IHTMLElement表示网页中的一个基本的元素。而象IHTMLOptionElement接口就表示一个特定的元素Option。基本的元素都有setAttribute和geAttribute方法来动态的设置和得到元素的名称和值。

    —- 较为常见的一个应用是我们能够分析网页中是否有需要填写的Forms,如果这个网址的Forms以前已经填写过而且数据我们已经保存下来的话,我们就可以把数据自动放到和该URL下的Forms的相关的位置中去。另外,我们可以总结网页上需要填写的Form的数据项,先对这些数据项进行赋值,以后碰到有相同的数据项的时候就自动把我们赋值的内容填写进去。实际上Form是对象,Form中包含的元素,比如INPUT,OPTION,SELECT等类型的输入元素都是对象。

    —- 另外一个可以想到的应用是自动对网页中的文本进行翻译,因为我们可以修改网页中任何对象的属性,所以我们可以把里面不属于本国语言的部分自动翻译成本国语言,当然真正的实现还要靠自然语言理解方面技术的突破,但是IE浏览器的接口和对象的形式使我们能够灵活的控制整个IE,无论是从事件对象还是到网页对象。

    —- 5.小结

    —- 上面我们分析了如何得到所有IE的实例,同时介绍了和IE实例相捆绑的DLL的详细的实现机制,同时对网页的对象化进行了分析。并且介绍了几个相关的应用和实现的方法及存在的技术问题。IE是一个组件化的以COM为基础的浏览器,它具有强大的功能,同时为应用开发者留下了广阔的空间,当然它也存在体积比较大,速度相对比较慢的缺点。但是它的体系结构代表了微软先进的创新的技术,因此具有强大的生命力。

    0

    Toolband (Toolbar for IE) sample using WTL


    转至: http://www.codeproject.com

    Sample Image - toolband10.gif


    Credits and Acknowlegements

    This module is based on the ATL DeskBand Wizard article that was created by Erik Thompson. My thanks goes to him for producing a great wizard that saves you the nity grity of creating DeskBands.

    Please note that this project does not use MFC, for all those MFC die hards that want to use MFC in their Tool Bands I suggest you down load the KKBar sample from microsofts MSDN site.

    The KBBar Sample can be downloaded from here

    Creating the ToolBand Module

    You will need to install the ATL DeskBand Wizard in order to create ToolBands. Please follow the instruction in this article.

    The best way to kick start a Tool band project is to use the ATL COM App Wizard. The COM Object needs to be in-proc therefore choose ‘DLL’ as the Type. The rest of the options can be kept in there default state. (Note this project does not use MFC, as the project is based on ATL and )

    Once you have a ATL COM Project, You can use the ATL DeskBand Wizard to create the Initial Tool Band.

    Adding Support for WTL

    You will require the WTL Libraries, these can be downloaded from the microsoft site

    See Installation of WTL

    The following header files needs to be added to stdafx.h file

    atlapp.hatlwin.hatlctrls.hatlmisc.h

    Create the

    You can create your toolbar in the usual way via the resource editor, Once you have your toolbar you need to create the toolbar dynamically. The CBandToolBarCtrl is inherited from CToolBarCtrl and is used to create the toolbar dynamically.

    DWORD dStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |                CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN |                TBSTYLE_TOOLTIPS | TBSTYLE_FLAT;    HWND hWnd = m_wndToolBar.CreateSimpleToolBarCtrl(hWndChild, IDR_TOOLBAR_TEST,                                                  FALSE, dStyle); 

    This is done in the RegisterAndCreateWindow function that is called from SetSite method.

    Message Reflection

    The best way to handle the messages of the toolbar is to let the control handle its own messages via "Message Reflection". The best way to reflect the messages is to create an invisible control that acts as the parent for the toolbar. The invisible control will reflect the toolbar messages back to itself. See CBandToolBarReflectorCtrl for the invisible control that will be used.

    The following code shows the parent child relationship that is used to achieve Message Reflection.

    BOOL CToolBandObj::RegisterAndCreateWindow(){    RECT rectClientParent;    ::GetClientRect(m_hWndParent, &rectClientParent);    // We need to create an Invisible Child Window using the Parent Window,     // this will also be used to reflect Command    // messages from the rebar    HWND hWndChild = m_wndInvisibleChildWnd.Create(m_hWndParent,                                                    rectClientParent,                                                    NULL, WS_CHILD);        // Now we can create the Tool Bar, using the Invisible Child    DWORD dStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |                    CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN |                    TBSTYLE_TOOLTIPS | TBSTYLE_FLAT;        HWND hWnd = m_wndToolBar.CreateSimpleToolBarCtrl(hWndChild,
    
                                                         IDR_TOOLBAR_TEST,                                                      FALSE, dStyle);     m_wndToolBar.SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS);              m_wndToolBar.m_ctlBandEdit.m_pBand = this;    return ::IsWindow(m_wndToolBar.m_hWnd);}

    The following Macros are used to identify the reflected messages from the ordinary messages. e.g WM_COMMAND reflected comes back as OCM_COMMAND.

    #define OCM_COMMAND_CODE_HANDLER(code, func) \if(uMsg == OCM_COMMAND && code == HIWORD(wParam)) \{ \    bHandled = TRUE; \    lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \    if(bHandled) \    return TRUE; \}#define OCM_COMMAND_ID_HANDLER(id, func) \if(uMsg == OCM_COMMAND && id == LOWORD(wParam)) \{ \    bHandled = TRUE; \    lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \    if(bHandled) \    return TRUE; \}#define OCM_NOTIFY_CODE_HANDLER(cd, func) \if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \{ \    bHandled = TRUE; \    lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \    if(bHandled) \    return TRUE; \}

    Browser Navigation

    In order to Navigate on the browser you need to instantiate the IWebBrowser2 COM Object. This is usually done on the SetSite Method e.g.

    IServiceProviderPtr pServiceProvider = pUnkSite;if (_Module.m_pWebBrowser)    _Module.m_pWebBrowser = NULL; if(FAILED(pServiceProvider->QueryService(SID_SWebBrowserApp, IID_IWebBrowser,                                             (void**)&_Module.m_pWebBrowser)))return E_FAIL;

    Once you have the COM Object Instantiated, you can move to your URL using the navigate method

    	_variant_t varURL = _bstr_t(www.codeproject.com); _variant_t varEmpty;_Module.m_pWebBrowser->Navigate2(&varURL, &varEmpty, &varEmpty,                                     &varEmpty, &varEmpty);

    Drag and Drop Edit and ComboBox Control

    The CBandEditCtrl class is inherited from a WTL CEdit control that has drag and drop facility. i.e. you can drag text from the browser straight to the CEdit Control.

    The CBandComboBoxCtrl class is inherited from a WTL CComboBox control that has drag and drop facility. i.e. you can drag text from the browser straight to the CComboBox Control.

    Drag and Drop URL - toolband2.gif

    The Edit control in this sample module allows you to drag a URL from Explorer or any other Dragable enabled container. Once you have dropped the URL the toolband will go to that site.

    Configurable Toolbar Button Styles

    The CBandToolBarCtrl class allows you to have the follwoing button styles on the toolbar

    • Image and Text on the right
    • Image and Text on the bottom
    • Image only

    Text on Right - toolband3.gif

    No Text - toolband4.gif

    Text Under - toolband5.gif

    Pop-up Menu Tracking

    A pop up menu is used to get to the configuration options

    Popup Menu Tracking - toolband6.gif

    ToolTips

    This has been taken from MSDN to explain why you need to handle the tooltips on the toolbar your self.

    Tool tips are automatically displayed for buttons and other controls contained in a parent window derived from CFrameWnd. This is because CFrameWnd has a default handler for the TTN_GETDISPINFO notification, which handles TTN_NEEDTEXT notifications from tool tip controls associated with controls.

    However, this default handler is not called when the TTN_NEEDTEXT notification is sent from a tool tip control associated with a control in a window that is not a CFrameWnd, such as a control on a dialog box or a form view. Therefore, it is necessary for you to provide a handler function for the TTN_NEEDTEXT notification message in order to display tool tips for child controls.

    This can be easily done in WTL by using the following Message Handler in the overriden ToolBar Control

    NOTIFY_CODE_HANDLER(TTN_NEEDTEXT, OnToolbarNeedText)

    The following is the code that loads the tool tips from the resources and sets the tool tip text.

    LRESULT CBandToolBarCtrl::OnToolbarNeedText(int /*idCtrl*/, LPNMHDR pnmh, BOOL&                                             bHandled)	{    CString sToolTip;        //-- make sure this 1is not a seperator    if (idCtrl != 0)     {        if (!sToolTip.LoadString(idCtrl))        {            bHandled = FALSE;            return 0;        }    }    LPNMTTDISPINFO pttdi = reinterpret_cast<LPNMTTDISPINFO>	    (pnmh);pttdi->lpszText = MAKEINTRESOURCE(idCtrl);    pttdi->hinst = _Module.GetResourceInstance();    pttdi->uFlags = TTF_DI_SETITEM;    //-- message processed    return 0;}

    Update the Status Bar

    You can update the status bar using the browser method put_StatusText, this method can be used typically in the WM_MENUSELECT event

    The following is the code that loads up the menu text from the resources and displays it on the browser status bar.

    Collapse
    LRESULT CBandToolBarCtrl::OnMenuSelect(UINT /*uMsg*/,                                        WPARAM wParam, LPARAM lParam,                                        BOOL& bHandled) {    WORD nID = LOWORD(wParam);    WORD wFlags = HIWORD(wParam);        //-- make sure this is not a seperator    CString sStatusBarDesc;    if ( !(wFlags & MF_POPUP) )    {        if (nID != 0)         {            if (!sStatusBarDesc.LoadString(nID))            {	        bHandled = FALSE;                return 0;            }            int nPos = sStatusBarDesc.Find(_T("\n"));            if (nPos != -1)            {                sStatusBarDesc =                 sStatusBarDesc.Left(nPos+1);                _Module.m_pWebBrowser->                put_StatusText(_bstr_t(sStatusBarDesc));                return 0;            }        }    }    return 0;}

    How to add a Chevron to your toolband

    In order to add a chevron to your toolband you need to add the DBIMF_USECHEVRON flags to your GetBandInfo method in the DBIM_MODEFLAGS mask.

     ... if(pdbi->dwMask == DBIM_MODEFLAGS)     {         //AddChevron        pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT |                                   DBIMF_USECHEVRON | DBIMF_BREAK;    }...

    This basically add the ability to show the chevron, if you want to see it appear on your toolband, then you must make sure the pdbi->ptMinSize.x value is less then your pdbi->ptActual.x value (Again this values can be set in the GetBandInfo method.

    In order to handle the events of the button in the chevron menu, you must subclass the rebar control which is hosting your toolbar. The following steps have been used to sublass the rebar control

    1. Find the rebar control – This can be achieved by getting the browsers window handle and searching for all its child , until you find the rebar control.

    2. Once you have found the rebar control you can simply subclass it using an ATL CContainedWindow.

        BOOL CBandToolBarCtrl::SetBandRebar()    {         HWND hWnd(NULL);        _Module.m_pWebBrowser->get_HWND((long*)&hWnd);         if (hWnd == NULL) 	    return FALSE;	m_ctlRebar.m_hWnd = FindRebar(hWnd);	if (m_ctlRebar.m_hWnd == NULL) 	    return FALSE;	m_RebarContainer.SubclassWindow(m_ctlRebar);	return TRUE;    }

    Once you have subclass the window, the events should reach the toolbar class.

    Append to the Browser Context Menu

    Sample Image - toolband11.gif

    I tried to duplicate the google and codeproject toolband right mouse browser context menu searches without any luck, until I looked at the binary resources, I found that you can extend the internet explorer menu by adding the option in the registry. This can easily be achieved by adding an entry in your .rgs file.

    HKCU{    NoRemove Software    {        NoRemove Microsoft        {            NoRemove 'Internet Explorer'            {                NoRemove MenuExt                {                    ForceRemove '&Sample Toolband Serach' = s'res://%MODULE%/MENUSEARCH.HTM'                    {                        val Contexts = b '10'                    }                }            }        }    }}

    Note the value of the registry item (a script that exist in the resources of the module).

    see MENUSERACH.HTM under HTML in the module resource to see what the script is doing

    0

    字节对齐详解(x86 + ARM)


    一.什么是字节对齐,为什么要对齐?
       现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
       对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对 数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那 么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数 据。显然在读取效率上下降很多。

    二.字节对齐对程序的影响:
       先让我们看几个例子吧(32bit,x86环境,gcc编译器):
    设结构体如下定义:
    struct A
    {
       int a;
       char b;
       short c;
    };
    struct B
    {
       char b;
       int a;
       short c;
    };
    现在已知32位机器上各种数据类型的长度如下:
    char:1(有符号无符号同)    
    short:2(有符号无符号同)    
    int:4(有符号无符号同)    
    long:4(有符号无符号同)    
    float:4    double:8
    那么上面两个结构大小如何呢?
    结果是:
    sizeof(strcut A)值为8
    sizeof(struct B)的值却是12

    结构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的short型数据一个,B也一样;按理说A,B大小应该都是7
    之所以出现上面的结果是因为编译器要对数据成员在空间上进行对齐。上面是按照编译器的默认设置进行对齐的结果,那么我们是不是可以改变编译器的这种默认对齐设置呢,当然可以.例如:
    #pragma pack (2) /*指定按2字节对齐*/
    struct C
    {
       char b;
       int a;
       short c;
    };
    #pragma pack () /*取消指定对齐,恢复缺省对齐*/
    sizeof(struct C)值是8。
    修改对齐值为1:
    #pragma pack (1) /*指定按1字节对齐*/
    struct D
    {
       char b;
       int a;
       short c;
    };
    #pragma pack () /*取消指定对齐,恢复缺省对齐*/
    sizeof(struct D)值为7。
    后面我们再讲解#pragma pack()的作用.

    三.编译器是按照什么样的原则进行对齐的?
       先让我们看四个重要的基本概念:
    1.数据类型自身的对齐值:
     对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。
    2.结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。
    3.指定对齐值:#pragma pack (value)时的指定对齐值value。
    4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。
    有 了这些值,我们就可以很方便的来讨论具体数据结构的成员和其自身的对齐方式。有效对齐值N是最终用来决定数据存放地址方式的值,最重要。有效对齐N,就是 表示“对齐在N上”,也就是说该数据的"存放起始地址%N=0".而数据结构中的数据变量都是按定义的先后顺序来排放的。第一个数据变量的起始地址就是数 据结构的起始地址。结构体的成员变量要对齐排放,结构体本身也要根据自身的有效对齐值圆整(就是结构体成员变量占用总长度需要是对结构体有效对齐值的整数 倍,结合下面例子理解)。这样就不能理解上面的几个例子的值了。
    例子分析:
    分析例子B;
    struct B
    {
       char b;
       int a;
       short c;
    };
    假 设B从地址空间0×0000开始排放。该例子中没有定义指定对齐值,在笔者环境下,该值默认为4。第一个成员变量b的自身对齐值是1,比指定或者默认指定 对齐值4小,所以其有效对齐值为1,所以其存放地址0×0000符合0×0000%1=0.第二个成员变量a,其自身对齐值为4,所以有效对齐值也为4, 所以只能存放在起始地址为0×0004到0×0007这四个连续的字节空间中,复核0×0004%4=0,且紧靠第一个变量。第三个变量c,自身对齐值为 2,所以有效对齐值也是2,可以存放在0×0008到0×0009这两个字节空间中,符合0×0008%2=0。所以从0×0000到0×0009存放的 都是B内容。再看数据结构B的自身对齐值为其变量中最大对齐值(这里是b)所以就是4,所以结构体的有效对齐值也是4。根据结构体圆整的要求, 0×0009到0×0000=10字节,(10+2)%4=0。所以0x0000A到0x000B也为结构体B所占用。故B从0×0000到0x000B 共有12个字节,sizeof(struct B)=12;其实如果就这一个就来说它已将满足字节对齐了, 因为它的起始地址是0,因此肯定是对齐的,之所以在后面补充2个字节,是因为编译器为了实现结构数组的存取效率,试想如果我们定义了一个结构B的数组,那 么第一个结构起始地址是0没有问题,但是第二个结构呢?按照数组的定义,数组中所有元素都是紧挨着的,如果我们不把结构的大小补充为4的整数倍,那么下一 个结构的起始地址将是0x0000A,这显然不能满足结构的地址对齐了,因此我们要把结构补充成有效对齐大小的整数倍.其实诸如:对于char型数据,其 自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,这些已有类型的自身对齐值也是基于数组考虑的,只 是因为这些类型的长度已知了,所以他们的自身对齐值也就已知了.
    同理,分析上面例子C:
    #pragma pack (2) /*指定按2字节对齐*/
    struct C
    {
       char b;
       int a;
       short c;
    };
    #pragma pack () /*取消指定对齐,恢复缺省对齐*/
    第 一个变量b的自身对齐值为1,指定对齐值为2,所以,其有效对齐值为1,假设C从0×0000开始,那么b存放在0×0000,符合0×0000%1= 0;第二个变量,自身对齐值为4,指定对齐值为2,所以有效对齐值为2,所以顺序存放在0×0002、0×0003、0×0004、0×0005四个连续 字节中,符合0×0002%2=0。第三个变量c的自身对齐值为2,所以有效对齐值为2,顺序存放
    在0×0006、0×0007中,符合 0×0006%2=0。所以从0×0000到0×00007共八字节存放的是C的变量。又C的自身对齐值为4,所以C的有效对齐值为2。又8%2=0,C 只占用0×0000到0×0007的八个字节。所以sizeof(struct C)=8.

    四.如何修改编译器的默认对齐值?
    1.在VC IDE中,可以这样修改:[Project]|[Settings],c/c++选项卡Category的Code Generation选项的Struct Member Alignment中修改,默认是8字节。
    2.在编码时,可以这样动态修改:#pragma pack .注意:是pragma而不是progma.

    五.针对字节对齐,我们在编程中如何考虑?

       如果在编程的时候要考虑节约空间的话,那么我们只需要假定结构的首地址是0,然后各个变量按照上面的原则进行排列即可,基本的原则就是把结构中的变量按照 类型大小从小到大声明,尽量减少中间的填补空间.还有一种就是为了以空间换取时间的效率,我们显示的进行填补空间进行对齐,比如:有一种使用空间换时间做 法是显式的插入reserved成员:
            struct A{
              char a;
              char reserved[3];//使用空间换时间
              int b;
    }

    reserved成员对我们的程序没有什么意义,它只是起到填补空间以达到字节对齐的目的,当然即使不加这个成员通常编译器也会给我们自动填补对齐,我们自己加上它只是起到显式的提醒作用.

    六.字节对齐可能带来的隐患:
       代码中关于对齐的隐患,很多是隐式的。比如在强制类型转换的时候。例如:
    unsigned int i = 0×12345678;
    unsigned char *p=NULL;
    unsigned short *p1=NULL;

    p=&i;
    *p=0×00;
    p1=(unsigned short *)(p+1);
    *p1=0×0000;
    最后两句代码,从奇数边界去访问unsignedshort型变量,显然不符合对齐的规定。
    在x86上,类似的操作只会影响效率,但是在MIPS或者sparc上,可能就是一个error,因为它们要求必须字节对齐.

    七.如何查找与字节对齐方面的问题:
    如果出现对齐或者赋值问题首先查看
    1. 编译器的big little端设置
    2. 看这种体系本身是否支持非对齐访问
    3. 如果支持看设置了对齐与否,如果没有则看访问时需要加某些特殊的修饰来标志其特殊访问操作。

    八.相关文章:转自http://.csdn.net/goodluckyxl/archive/2005/10/17/506827.aspx

    ARM下的对齐处理
    from DUI0067D_ADS1_2_CompLib

    3.13 type  qulifiers

    有部分摘自ARM编译器文档对齐部分

    对齐的使用:
    1.__align(num)
      这个用于修改最高级别对象的字节边界。在汇编中使用LDRD或者STRD时
      就要用到此命令__align(8)进行修饰限制。来保证数据对象是相应对齐。
      这个修饰对象的命令最大是8个字节限制,可以让2字节的对象进行4字节
      ,但是不能让4字节的对象2字节对齐。
      __align是存储类修改,他只修饰最高级类型对象不能用于结构或者函数对象。
     
    2.__packed
     __packed是进行一字节对齐
     1.不能对packed的对象进行对齐
     2.所有对象的读写访问都进行非对齐访问
     3.float及包含float的结构联合及未用__packed的对象将不能字节对齐
     4.__packed对局部整形变量无影响
     5.强制由unpacked对象向packed对象转化是未定义,整形指针可以合法定
     义为packed。
        __packed int* p;  //__packed int 则没有意义
     6.对齐或非对齐读写访问带来问题
     __packed struct STRUCT_TEST
    {
     char a;
     int b;
     char c;
    }  ;    //定义如下结构此时b的起始地址一定是不对齐的
            //在栈中访问b可能有问题,因为栈上数据肯定是对齐访问[from CL]
    //将下面变量定义成全局静态不在栈上
    static char* p;
    static struct STRUCT_TEST a;
    void Main()
    {
    __packed int* q;  //此时定义成__packed来修饰当前q指向为非对齐的数据地址下面的访问则可以

    p = (char*)&a;          
    q = (int*)(p+1);      

    *q = 0×87654321;
    /*  
    得到赋值的汇编指令很清楚
    ldr      r5,0×20001590 ; = #0×12345678
    [0xe1a00005]   mov      r0,r5
    [0xeb0000b0]   bl       __rt_uwrite4  //在此处调用一个写4byte的操作函数
         
    [0xe5c10000]   strb     r0,[r1,#0]   //函数进行4次strb操作然后返回保证了数据正确的访问
    [0xe1a02420]   mov      r2,r0,lsr #8
    [0xe5c12001]   strb     r2,[r1,#1]
    [0xe1a02820]   mov      r2,r0,lsr #16
    [0xe5c12002]   strb     r2,[r1,#2]
    [0xe1a02c20]   mov      r2,r0,lsr #24
    [0xe5c12003]   strb     r2,[r1,#3]
    [0xe1a0f00e]   mov      pc,r14
    */

    /*
    如果q没有加__packed修饰则汇编出来指令是这样直接会导致奇地址处访问失败
    [0xe59f2018]   ldr      r2,0×20001594 ; = #0×87654321
    [0xe5812000]   str      r2,[r1,#0]
    */

    //这样可以很清楚的看到非对齐访问是如何产生错误的
    //以及如何消除非对齐访问带来问题
    //也可以看到非对齐访问和对齐访问的指令差异导致效率问题
    }

    0

    《越狱》第二季口语重点


    《越狱》第二季口语重点 <PrisonBreak season2>
    作者charlotte85
    请勿用于任何商业用途,转载请注明作者及出处。
    http://bbs.prisonbreak.cn/viewthread.php?tid=7000&extra=page%3D1&page=1

    第一集
    1.And he’s the mastermind of this whole thing. 他是整个事情的主谋
    mastermind=策划者,主谋
    2.he acknowledge that whatever neuroses drove the criminal to commit the original crime is compounded.他知道无论是什么神经机能病变导致的最初犯罪都是复杂的
    commit the crime=犯罪
    acknowledge =承认,知道
    3.You’re not being very transparent,Warden. 你不是很坦率,狱长
    transparent=透明的
    4.But it’s going to make collaboration kind of hard. 不过这样合作起来就不那么容易了
    collaboration=cooperation 协作,合作
    5.i’m the furthest thing from a threat.我根本没有威胁
    这句话体现了老外说话的艺术性,非直来直去的表达自己的意思,譬如老外喜欢用"is the ice cold?" 来表达"yes"之意
    6.why don’t you cut out all the riddles,snowflake,and just give us to a straight.你干嘛不把话说明点,小白脸.
    riddle=谜题
    straight除了"直"的意思外,也用于"异性恋者",反义是homosexual同性恋者
    7.the harder you struggle,the worse it gets你越挣扎,情况越糟
    这是我们在中文里经常听到的
    struggle=挣扎
    8.Self-presevation is a strong motivator.自卫是很强的因素
    self-presevation=self-protection 自卫
    motivator=动机,因素
    9.one thing you learn when you’re walking the steps is that you never outsource a blame that belons in your own backyard.当你经历这些,你学到的一件事就是你再不用寻求你所受到的责备
    walk the steps=一步步地经历下来
    10.you fell for her 你爱上了她
    等于我们常见的you felling in love with her
    11.Sir,I cannot do a procedure like this without an anesthetic. 先生,如果没有麻醉剂,我没法动这个手术 procedure=手术 ;anesthetic=麻醉药
    12.i want you to turn youself in.我希望你去自首
    这里的turn in 是"自首"的意思,若换成"i want you to turn him in"则turn in为"告发"的意思

    第二集
    1.yeah,yuck it up,funny man.耶,尽情大笑吧,可笑的人
    yuck up=开怀大笑
    2.we’re headed out,man 我们出发了,伙计
    3.That is absolutely hogwash. 简直一派胡言
    Hogwash=猪食
    4.how was scofield able to have exclusive access to you?为什么scofield能单独接触你?
    exclusive=专门的,独家的 ; access to=接近…
    5.This will be your last outburst,officer. 这将是你最后一次发飙了,长官
    outburst=爆发,发飙
    6.Is it true you sold the right to run prison industries to the highest bidder. 你将监狱工厂管理权卖给出价最高的人是不是真的?
    run=经营 eg. run a company 经营一家公司
    highest bidder=最高价竞买人7.We’ll call for you when we’ve reached a decision. 等我们做好决定后会通知你们
    reach a decision=作出决定 (注意reach的用法)8.your call.你决定吧
    常用口语
    9.This can go down humanely if you don’t fight,but if you pull a stunt like that again,it’s going to get inhumane right quick. 你要不挣扎的话,那接下来我将会很仁慈,不过要是你想再耍花招,我就会变得很残忍
    humanely=慈悲地 ;pull a stunt=耍花招 ;inhumane=残忍的
    10.if you would have just told us in the beginning that this was going to be a railroad.如果你一开始就告诉我们这是个快速通过案
    railroad在俗语中指"议案快速通过",泛指"铁路运输"
    11.But you need a fall guy,fine. 但是你们需要一个替罪羊
    a fall guy=替罪羊;替身演员
    12.he went out with his boots on.他死在工作岗位
    翻译组的译文是"他走得很平静",我觉得不确切.die with one’s boots on”,源自美国西部,它有两
    层含义。一为死于工作岗位(“die in harness”)、一为殉职,尤指在战斗中或者为高尚的事业而
    献身。因为如果是病死或老死的情况下,一般是躺在床上等待死亡,不会穿着鞋子;如果是在枪战中死去,自然是穿着靴子的。而在英式英语里,通常把它说成“die in one’s boots”。
    13.i failed him.我让他失望了.

    第三集
    1.well,Hector says that you can serve your full sentence.嗯,hector说你要刑满才释放.
    sentence=判决,宣判
    serve the sentence=服刑
    2.anything break on the other six.其他六人有什么进展?
    break=突破,进展
    3.Listen,you know I’m thankful for the help with the green card,but I just don’t want to get involved. 我很感激你帮我搞到绿卡但我不想卷入此事。
    be involved in sth=卷入…事情中
    4.those ass-hats are worth more dead than you and i are alives.那些混蛋就是死了也比我们值钱
    ass-hats=混蛋
    eg. ass hat inside 内心卑鄙的
    5.i hope you’re holding on to something tight ’cause i’m about to break it down for you.我希望你做好心理准备,因为我要说的东西会让你崩溃
    holding on to something tight牢牢扶助什么东西
    break down=崩溃
    6.you were attending when I first started here. 我刚来的时候你是主治医师。
    attending=主治的
    7.i want to alert you to a possible situation.我要提醒你可能发生的情况
    alert sb=warn sb 警告某人
    8.Give me one good reason why I shouldn’t turn you in right now. 给我个不告发你的理由。
    turn in=告发;上缴;上床睡觉
    9.we keep tapping on cracks,and she’s going to break.我们深入利用这个弱点,她就会崩溃
    tap on=轻轻敲打 ; crack=裂缝
    tap on cracks 敲打已有的裂缝,即深入利用弱点
    10.humpty dumpty climbed up a wall,humpty dumpty had a great fall.胖墩爬上墙,胖墩摔下来
    此句来源于一首童谣,humpty dumpty现在都用来称呼胖墩
    11.How do you throw the hunter off the scent?Get rid of the prey.你怎么才能逃过猎人的鼻子? 扔掉猎物。
    throw off=摆脱掉 scent=气味,嗅觉
    12.your tags are expired.你的车牌过期了
    expire=期满;死亡
    13.provided the transport comes though.若果交通顺利的话
    provied和provided that常用于数学属于中,为"假设,假如"的意思
    14.You have the right to speak to an attorney before you speak to the police.Anything you say may be used against you in a court of law. 在你向警方供述之前,你有权去请律师,但是你所说的一切将成为呈堂证供

    第四集
    1.We’ll drop you off in the next town,and I’ll wire you that 10,000 like I said.我们让你在下个镇下车,我会给你汇10000美元
    wire=汇款;诱饵
    2.Don’t even think about getting cute,smart-ass.And now,you and your brother are gonna take me right to where that money is,or the whore gets dead real fast.别耍花招,现在你和你哥带我们去藏钱的地方,不然这妓女会死的很快
    cute=狡猾的;花招 ; whore=妓女
    3.The dredging of the river under Scofield’s apartment bore some fruit. 从Scofeld公寓下的 河里打捞出了些东西
    dredging=捕捞 ; fruit=成果
    4.to forge ahead with its nuclear program 继续核武器的计划
    forge=锻造; ahead with sth=继续做…
    5.he’s got a stateroom listed as a cargo hold on the manifest.他将头等舱伪造成装货物的仓库
    stateroom=头等舱 ; cargo=货物 ; manifest=货单6.i travel light 我轻松旅行
    light做副词为"轻轻地"意思
    7.and you’re just hoofing it out here in the middle of nowhere?你就在中途闲逛?
    另外hang around也是"闲逛"的意思
    8.I admire your optimism.She’s rolling,man. 我很钦佩你的乐观,她在叛变
    admire sb=羡慕某人;钦佩某人
    rolling=转变,在此句中指"叛变"
    9.not in a thousand years.想都别想
    等于no way(没门),但比no way的拒绝程度更坚决
    10.you think that tire went flat by accident?你以为车轮瘪了是个意外么?
    flat=平的,扁的; 充气为inflate
    by accident=偶然的,意外的
    11.Don’t turn your back on us.别抛弃我们
    turn one’s back on / upon=背弃..,抛弃..
    eg.One should never turn his back on his home country. 一个人永远也不能背弃自己的祖国
    12.my dogs are just barking. 我走得脚痛
    此句是t-bag在被邀请搭个顺风车时说的,翻译组的翻译是"正合我意" . 原因是在美国的俚语中"my dogs are just barking"的意思是"我的脚走得都痛了"
    13.When dad’s back acts up,we stop. 当爸爸的背不舒服时我们就得停下来
    act up=运作不正常
    14.Hit a sore spot,didnt I? 说到你痛处了,是不是?
    sore spot=痛处,提起来就伤感情的话题
    15.it’s over for good 永远结束了
    for good=永远

    第五集
    1.I bought us some time-that’s what counts. 我争取到了时间,那才是最重要的。
    count=有价值
    2.What you call it?Double K Ranch.No.You from around here? Yeah,born and raise.你说哪里?双K农场。没听过。你是这里人吗?是的,土生土长。
    Ranch=大农场
    born and raise=土生土长
    3.thanks for your time.谢谢你的配合
    这是实用而简单的口语,当你耽误了别人时间时最好都说一声thanks for your time
    4.every plot is mapped out with dimensions.每一小块都会用尺寸标注出
    map with=标示 ; dimension=尺寸
    5.Keep me posted. 和我保持联系
    posted=消息灵通的
    6.that’s my ego.是我自以为是了
    ego=自负,自我主义
    7.none of your beeswax.不关你事
    大家常见的是"none of your business",可用beeswax代替business
    8.Do you happen to have a pen handy? 你手头有笔吗?
    handy=唾手可得的,手边的
    9.they’re due west and we need to know why.他们都计划去西边,我们得知道为什么
    due=计划的
    10.that bitch treed herself and i brought her down in one shot.那个贱人困住了自己,我一枪射中
    tree sb 口语中表示"使某人陷入困境"
    11.i’ll ring it up.我来打价
    超市里打价都是"滴"一声,ring up 由此得来
    12.before i destroyed it,i committed it to my photographic memory.在我销毁它之前,我把它存入我的相机一样的记忆中了
    commit=委托,托负
    photographic =摄影般的
    13.now let’s not dissolve into threats,all right.别化为恐吓好么?
    14.Probably out of your price range. 恐怕你买不起

    第六集
    1.I want to don’t hear anything out of your mouth other than what yourphotograpic…map除了你说关于地图的事,其它事我都不要听
    want to 在口语里读成wanna other than=除了we’re pulling them now.我们在全力以赴
    2.we’re going to get made out here.我们会被认出的
    make out=辨认出
    3.oh ,shut it 哦 闭嘴吧
    4.我们一般多用shut up,shut it语气没shut up 强烈
    something was in their way 有东西挡着它们
    特口语的说法,本集里说的是仓库档着树的阳光,也可用于XX东西阻碍了什么什么的发展
    5.if we hit the foundation,we stay
    hit the foundation=触到地基
    6.we got to do something and it’s not going to involve hurting anyone 我们要干点什么,但不能伤人
    involve doing sth=包括…then gas up the car 给车加满油
    7.can I hitch a ride? 我能搭个便车吗?
    hitchhike=徒步搭过路车式的旅行
    8.Fresh out of the academy 一毕业就开始了
    9.If you’re telling me the road to him leads through Sara Tancredi ,by all means,pursue it.如果你认为抓到他必须利用到ST,那就用任何手段继续下去
    这个词组蛮好用的,road to sb/sth leads through sb/sth是很形象的说法=达到。。。必须通过。。。。
    by all means=用尽一切方法
    10.The president has unwavering faith in you.总统对你很有信心
    unwavering也是好的用法=不动摇的,意志坚定的,可替代unchangeable
    11.Now feel free to call your company
    feel free to 请便
    12.we’re ready to turn your juice back on 我们准备好去恢复你家的电力
    juice=<俚语>电流
    13.the niose might be substabtial噪音会很大
    substabtial的意思很多,这里指“相当的”,除此之外,它还有“实际的;重要的;真实的;坚固的”等含义
    14.What’s up,snowflake?
    snowflake表面意是“小雪花”,引申义是白种高加索人不友好的称呼,可见C-NOTE对MS的不满
    15.ask him if he would like have a drink with me after the punches out?问问他下班能和我喝一杯吗?
    punch 有打孔的意思,punch out引申为“打卡下班” punch in则同理为“打卡上班”

    第七集
    1.Just go easy.放松点
    2.Go nothing.别动
    警察的惯用语是:Freeze! 即"别动"的意思
    3.It was 1:00 PM when they tangled it up.他们在下午一点聚集在一起
    tangle up 集中在一起
    4.The guy id’d both of them 那个人认出了他们两
    ID=identify,鉴别,识别,id card=身份证
    5.your car’s empty.
    car=超市里用的手推车
    6.It’s time to get the hat.我们该去拿钱了
    hat在这里不是"帽子"=非法所得的收入
    7.We have already committed the crime.我们已经犯罪了
    committe the crime犯罪
    committe the suicide自杀
    8.The hat’s over the wall.犯罪已成事实
    9.There was a way we could wipe the slate clean.这样我们可以洗清冤屈
    wipe the slate clean 是个再常用不过的词组,你会在很多电影和歌词中碰到,意思为"勾销往事 洗清冤屈"
    slate=石板, 古人会把罪犯的名字刻在石板上
    9.it looks like we’re back to square one.看来我们又回到起点了
    10.They withdrew his nomination他们撤销了对他的提名
    withdraw=撤销;撤退 nomination=提名
    11.oh,hit me a nerve 哦,真吓人12.knock it off. 安静
    13.whatever you got eating at you,you just give it up.无论什么事在折磨你,你就让它去吧(即别让这种内疚折磨你
    14.Bodies kept stacking up.
    stack up=不断堆积 body=尸首
    15.The picture makes me look like a sociopath.照片上的我跟精神变态者似的
    这里教一个猜单词词义的方法 sociopath: socio-为单词前缀=社会 -path为单词后缀=恨
    所以sociopath可翻译成憎恨社会的,反社会的
    16.Keep your head down.小心撞头,引申为"小心行事"
    17.She found no signs of foul play.她没发现谋杀迹象
    foul play原义为"球场上的严重的恶意的犯规"

    第八集
    1.The money was never yours to begin with.本来就不是你们的钱
    to begin with=本来,原先
    2.you are outnumbered and we will come after you.你人数少,我们会追上你的
     outnumber=数量上胜过
     come after 追上
    3.i let that psychopath t-bag loose once.我让T-BAG那个变态逃掉一次
     psychopath=精神变态者
     4. i didn’t mean to startle you. 我没想吓你。
     startle=使吃惊
    5.in an apparent attempt to avoid jail time.有意逃避入狱
     avoid+n./doing sth.
    老外喜欢用名词+time,表"一段什么的日子"
    6.that stuff on that table is premium.桌子上放着保险费
     很多人说"东西"时喜欢用"thing",其实stuff是最贴切的
    premium =n.保险费   a.高价值的 
    7.here is a list of options available to you.单子上提供的东西对你有用
     available在口语中是常用的词,譬如问别人有没有空"are you available today?",或问座位有没有人占"is the seat available?"
    8.Places to stay,business that are more open to hiring men out of the correctional system. 能住的地方,优 先聘用劳改犯的商家。
      be open to=对…开放; correctional system=引申为教改所
    9.without the money,we are screwed 没有钱我们就完了
    screw=螺丝钉,此处用被动,表示被牢牢定住了 
    10.we ran into some car trouble 我们遇到车祸了
    run into=遭遇,撞上
    11.They’re ladies’ clubs — I’m guessing they’re hotter than a monkey’s jock strap.那些小妞的酒吧,我猜她们比猴子的护裆还热
      Jockstrap是指男用的护裆(打壁球容易被球反弹击中),大家都知道猴子的PP是红的嘛,所以monkey’s jock strap红热红热的。。
    12.we got to lose the bike. 我们得扔掉这车。
    throw,leave 用腻了,用用lose也不错
    13.from a public relations standpoint,abruzzi and apolskia were by the book.从公众角度出发,(杀)abruzzi and apolskia是按规定的。
      standpoint=立场,观点
      by the book=按常规,按规矩
    14.your brilliant plan to eliminate sara tancredi from the equation failed.你的伟大的铲除SARA的计划,失败得也如此“伟大”
      一个brilliant一个和equation,把讽刺意味表露无疑
    15.It’s a simple strategy,plays across the board. 很简单的策略,广为人知
    16.Get some two-bit job? 找份廉价工打打?
    two-bit=二毛五分,即廉价的
    17.and then when you strat running out of air…当你没气的时候
     在学校学的都是“out of breath”
    18.i will chain you to this desk until i get some answers i cannot fertilize my lawn with
    我就把你困在这儿,寻找答案,找到我不能再找为止 fertilize=施肥  lawn=草坪
     这里用了个比喻,i cannot fertilize my lawn with原义“直到我的草坪施肥到不能再施为止”

    第九集
    1.I’ve been working.Uh,night shifts,cleanup and…Jimmy said I could change my shift 我一
    直在这儿工作,上的晚班,负责打扫,jimmy同意我换班
    the night shift=夜班;the day shift=白班 ;three shifts=三班倒
    2.copy that.收到
     copy在口语中常用于"收到/听到"
    eg. Do you copy?收到了吗?
      Roger. 收到了
    3.all the charges against you have been dropped,you’re free and clear to start a new life.
     你身上所有的指控都撤销了,你可以重新开始新的生活了
     drop在这里意为"删去"  
     指控:charge somebody with
    4.Not be constantly running,looking over your shoulder不用到处躲藏,小心翼翼地生活
    constantly=不时的,频繁的
     looking over your shoulder小心翼翼,时刻警惕
    5.was there any opprtunity to subdue him? 是否有机会制服他?
     subdue=打败,使顺从
    6.But sometimes things happen that are just out of your control.但有时候事情的发展会超出你
    的控制(M叔叔深刻的教训啊~这句不错)
    7.care to comment? 有啥想说的么?
     want to用腻了就用care to吧,同样是"愿意,想要"的意思
    8.i believe i said no comment.我说过无可奉告了
     no comment=无可奉告
    9.God help the who goes behind my back and talks to the press.上帝保佑那个背着我向媒体通风报信的家伙(别被我抓到)
     go behind sb’s back=背着某人
      press=新闻界,媒体
    10.the only way to win a war is to try to konw your prey completely.知己知彼,百战不殆
      prey=对手
    11.everything’s arranged.一切就绪
     everything’s arranged=everything’s ready
    12.let’s roll out.我们出发吧
      let’s roll out=let’s go
    13.We don’t have to ditch the car. 我们不必丢弃这辆车。
    ditch=放弃;挖沟
    14.It’s a one-shot deal out of the country. 这是离开这个国家的惟一的机会。
      shot=射击;one-shot=一射即出的,即"只有一次的"
    15.i just figured that since we were divorced…我只是发现自从我们结婚后...
      figure和figure out 在口语中非常常用,为"发现,觉得"的意思
    16.the bureau take its toll on your family.当局给你家带来了损害
      bureau=局
      toll=损失,代价
    17.can you guarantee me that my family ain’t going to get hurt?你保证我家人不会受伤?
    这里说说promise和guarantee的区别:两者都为"保证,确保",但promise的"保证"比    
    guarantee要弱很多.
      eg. i promise that i’m on your side.我尽量保证支持你(即如果事情有变我可以背叛你)
        i guarantee that i’m on your side.我誓死保证支持你
    18.nobody’s punking out没人退出
    punking out =退出
      这里再教大家一个新用法--punkd=被耍了
      i’m punkd 即"我被耍了"
    19.he’s a closed book.他很自我保护  
    20.All you have to do is wait by the merry-go-round. 你要做的就是等在旋转木马旁
    merry-go-round=旋转木马
    21.Alex was consumed with finding him.Alex费尽气力去找他
    22.you’re slipping.你错了
      slipping=wrong
    23.two caucasian males on foot ,fleeing the willcox station.两个白种男人徒步从willcox火车站逃逸
      (这里可以看出警察的训练有素,短短一句话就把细节都说明了)
      caucasian=高加索人的,白种人的
    flee=逃走

    第十集
    1.he ain’t coming off the goods.他什么都不说
     come off就是二个原来在一起的东西分开的意思
    2.i’m on my way and I need your talents,on the ground as well. 我正在赶去,我需要你的帮助
    on the ground=从基础开始
     另外与之相对的hit the ceiling的意思的"暴跳如雷"
    3.You wanted me to figure out Scofield’s rendezvous with Tancredi? 你想我找出Scofield和Tancredi的       会面地点么?
     rendezvous=集合点
    4.I’m sitting right on top of it. 我就快得手了
    on top of=了解知道,熟练掌握
    5.i could drop you back off with the crops if you’d prefer.若你喜欢我可以把你们再还给警察
     drop… back off=退还给
    6.she’s picking me uo in a few hours.她一会来接我
     pick up 是常用口语,意为"接某人上车",或"搭便车"
    7.Running away into the sunset with the man who lied to me? 和一个骗我的男人一起逃亡?
    sunset=日落;晚年(这里两种意思都有吧^^)
    8.he’s not gonna call for backup.他不会叫后援的
     back up=后援,增援
    9.i don’t wanna get trapped in here.我不想被困在这里
     trap=陷阱         be trapped in=被困住
    10.you are somebody.你是个大人物
     同样的,i’m nobody意思就是"我是个小人物"
    11.you’re on the wrong side.你站错了立场
     on sb’s side 站在某人一边
     eg.i’m on your side.我站在你这边,我支持你
    12.This is a monumental moment for both of us. 这是我们的重要时刻
      monumental=纪念碑的,即不朽的
    13.i’m not kidding around.我没有开玩笑
      i’m not kidding太常用啦
    14.you named him after yourself.他跟你姓
      name A after B=A以B命名
    15.Well,thanks for bailing as out. 谢谢你把我们弄出来
     bail=保释
    16.Down by the border. 南部的边境
    up by the border. 北部的边境

    第十一集
    1.this is the tribune police.make yourself known.我们是警察,请表明身份
    tribune=保护百姓的官
    make yourself known=表明身份
    2.cops found your girlfriend fish-belly white,gargling her own puke.警察发现你女朋友不省人 事,口吐 白沫
    fish-belly=鱼腹;fish-belly white=鱼翻白肚,即生命岌岌可危
    gargle=漱口 ; puke=呕吐物
    gargling her own puke口吐白沫(若换成字面意思挺恶心*_*)
    3.bring her down 将她打垮了
    这里再说另一个常用的词组let sb down,即"使某人失望
    4.the analyst got his hands on a phone conversation.分析员得到一通电话交谈
    get a hand on sth=得到…
    5.And judging by how hard they’re going after sara tancredi,i’m pretty sure they think she has it.以他们追捕sara的力度看,我很确定她有(带子)
    judge by=以…为判断 (因为这里的主语为I,所以用judge的动名词)
    go after=追逐;追求
    在动词前加上pretty,加深程度
    6.But i hope his death properly illustrates the magnitude of the situation that we’re in right now. 但我希望他的死完全说明了我们的麻烦,已经很严重了。
    properly=适当地,完全地; illustrate=举例说明,阐明; magnitude=大小
    7.are you aware of the nature of your sins?你知道你犯的罪的性质么?
    be aware of=知道,了解
    nature=(神学中)性质,种类
    sin=罪,其实sin和一般的罪不一样,它一般指人的原罪Original sin,如大家所熟悉的"七宗罪"(七宗
    罪即:Gluttony 暴食 Greed 贪婪 Sloth 懒惰 Pride 自负 Lust 淫欲 Envy 嫉妒 Warth 愤怒)
    8.What are those ends? 这些的目的是什么?
    9.surrender your will to god.屈服于上帝
    surrender=投降 ; wil=意愿
    10.I don’t like being out in the field,I only do so when there’s been a screw up. 我不喜欢抛头露面,我只在事情办砸的时候才出来
    screw up=事情办砸 eg.sorry,i screw it up 对不起,我把事情搞砸了
    11.you have my word.我保证
    实用口语12.Yeah,but i mean it. 是的但是我是认真的
    实用口语
    13.Do you think i’m just withholding information because i like hanging out with you.你以为我隐瞒消息是因为喜欢和你待一起么?
    withhold=保留,隐瞒
    hang out with sb=与某人待在一起
    14.Don’t try to float a babe-in-the-woods routine by me. 别想耍我把我当成不懂事的小孩
    babe-in-the-wood(s)=涉世未深的人,幼稚盲从的人,无经验而易受骗的人
    15.It’s really going to piss me off.这可真会把我惹火
    piss off=滚开
    16.I already named my price. 我已经开价了
    注意name的用法
    17.you’d better get down on your knees and pray to god that i don’t find you.你最好跪下祈祷我不会找到你
    get down on your knees=双膝跪下18.kiss my ass,cobarde.求我吧,懦夫
    kiss sb’s ass求某人,讨好某人
    相反,kick sb’s ass的意思为"揍某人一顿"

    第十二集
    1.They put me with this foster father down on pershing avenue.他们让我和住在pershing大街的养父一起生活.
    foster-father=养父. 另外step-father=继父
    avenue=林荫道,大街
    2.Apparently,you were some kind of analyst.That’s the job you chose over your family. 显然你是个分析家,你就为了那工作不要家了。
    3.Michael,turning on the company put me and you at even greater risk.Michael,跟公司作对会让你们和我冒更大的危险
    我们常见的turn on是指"打开,拧开",在此处trun on (sb)指"攻击"
    eg.Why are you all turning on me ? 你们为什么都冲我来了?
    另外,turn sb on=使某人激动或兴奋
    4.You must be relieved that it’s over. 这事结束了你就解脱了
    relieve=放心,解脱
    5.we don’t get a whole bunch of homicides out here,and,well,we’re trying to play catch-up.我们还没抓到那帮逃犯,我们正努力呢
    a bunch of=一堆,一群 ; homicide=杀人犯
    6.we can each sniff out a perp like a hot fart.我们能查觉谁是罪犯,就像闻臭屁一样
    sniff out=闻到;查觉到 ; fart=[俗语]屁
    perp=罪犯,为perpetrator的缩略
    7.I’d be indebted. 我很感激
    indebted=感恩的;负债的
    8.I’ll do whatever i can to help you nail that son of bitch.我会尽我所能去帮你们抓住那个狗娘养的
    nail=指甲;钉住;[俚语]抓住 (在此句中表"抓住")
    9.He got me clean through.他打穿我的身体了
    clean=整个地. eg.The bullet went clean through his shoulder. 子弹整个儿穿过了他的肩膀
    10.it’s a backup.这是后备的
    backup=后援;替代的
    而词组back up=支持;倒退
    11.Geary and me had a little dustup over how to go about finding bagwell.Geary和我在对于怎么寻找bagwell的问题上出现了纠纷
    dustup=纠纷,争执
    12.All we need to do is find a pharmacy. 我们要找的就是个药店
    pharmacy=药房,制药业
    13.I’ll make sure that everybody involved knows that your help was invaluable. 我保证每个有关人员都知道你的帮助是无价的
    invaluable=无价的
    in-和un-都是表"不"的前缀,但invaluable是指"无价的,珍贵的",unvalued才是指"无价值的,没用的"
    14.And i want to cut a deal first.我想先做个交易
    cut a deal 并不是破坏一个交易。相反地,to cut a deal就是在做生意方面,或者是在司法方面和对方 达成一个协议
    15.A little incentive,and i want it in writing. 以防万一,我要书面承诺。
    16.When we found the money,Geary double-crossed me. 当我们找到钱时,Geary出卖了我
    double-crossed=欺骗,出卖
    17.Now,at this juncture,thing will go a whole lot easier for you if you admit to the crime.事情到这份上,你还是早早认罪的好
    at this juncture=在这个当口上,在这个节骨眼上
    18.Bagwell set me up.bagwell陷害我
    set up是一个常用的词组,用法很灵活,有"竖起;排版;创立;张贴;树立(榜样);装置、安放…."一堆意思

    第十三集
    1.Until we verify,you will drop your weapon or we will drop you.在我们核实之前,放下武器,不然我们就放 倒你
    2.There men are in my custody. 我抓住了两个逃犯
    in custody=被拘留
    3.I was wondering if you could help a brother out.我想问问你能否帮兄弟我一个忙.
    我们都知道help sb是"帮助某人",help sb out 即"帮助解决难题,帮助摆脱困境,救出 "
    4.Remain at large. 仍逃亡在外
    at large=未被捕
    5.How a guy goes about getting a hold of one of those prosthetic jobbies. 一个人怎么才能得到假肢?
    get hold of=得到 ; prosthetic=[医]修补学,装补学
    6.He just neglected to tuck in the sheets. 他(医生)只是忽略我了
    这里说一下neglect,overlook, ignore的区别,虽然三个单词都表"忽视,忽略"的意思,但neglect指因粗心或遗 忘而没有事,ignore指有意识地拒绝、故意不予理会;overlook指由于草率或没有注意到而忽视某事。
    在搭配上, neglect除了可接sb.或sth.之外,还可接to do sth或doing sth作其宾语,而ignore 后面只可接sb. 或sth.不可接不定式。
    7.You sure as hell can figure out how to get a prosthetic for that stump of yours by yourself. 你自然能给自己搞个假肢
    as hell=表示强调,意为“非常”
    hell 在口语中使用频率很高,经常见到的由hell构成的词组还有:
    1)a / one hell of 表示强调,意思为“极好的/极糟的”。
    e.g. Forrest Gump is a hell of a good soldier. 阿甘是一个绝对出色的士兵
    2)go to hell 去你的,见鬼去吧
    3)feel / look like hell (感觉或气色)很差
    4)the hell表示强调,意思为“到底”
    stump=截肢
    8.with his escape,the aiding and abetting charges the felonies he’s racked up along the way,on top of his original sentence,I’d say Mr.Scofield will be spending the rest of his life behind bars.介于他越狱,协助并教唆犯罪等种种重罪指控,我得说Scofield要在监狱渡过余生了
    abet=怂恿,教唆 ; rack up=积累 ; behind bars=坐牢
    9.We’re entitled to a phone call. 我们有打电话的权利
    be entitled to do sth.=有权利,有资格做某事
    10.So sit tight.所以给我好好坐着
    tight=安稳的
    sleep tight="睡个好觉"
    11.What you’re asking me to do is tantamount to suicide. 你要我干的事相当于让我自杀
    tantamount to=等价于
    12.Pardon my forwardness. 原谅我的粗鲁
    pardon=原谅,宽恕 ; forwardness=卤莽;热心
    13.there’s sure to be a moment or two of chaos.会有一小会儿骚乱
    a moment or two=一会儿
    chaos=骚乱,吵杂 (教一个音忆法 chaos–chao+s,用汉语拼音读就是"吵死" ,这个词一下就能记住啦^ ^)
    14.Refresh my memory. 我回忆一下
    15.there is just one teensy-tiny thing i been meaning to ask.我只要求你帮个一个小小的忙
    tessy=[俗]极小的=tiny ; teensy-tiny=小之又小的
    16.copy that.收到
    常用口语
    17.You just found your inside man,but it’s got to be right now. 你们得找个知情人,不过我们现在就得行 动
    inside man=知情人,线人

    第十四集
    1.Give me a medevac,asap!我需要医疗直升飞机,快点!
    medevac=医疗后送直升飞机
    asap=尽快,为"as soon as possible"的缩写,在紧急情况下读成"asap"以节省时间
    2.No offense,sir,but we’re searching every vehicle.恕我冒犯,但我们在搜查每一辆车
    no offense在美语中很常用,当你要指出别人的缺点,或者表示不同观点的时候,都可以加这样一句,表示没有故意要冒犯的意思.另外,no offense如果用在打球方面,就是一方没有进攻,或没有得分
    3.That means,that at this stage,every second is critical.So if you detain me for one moment more,i will have all of your jobs. 这说明,眼下每一秒都至关重要.如果你们再妨碍我,我就让你们都失业
    at this stage=眼下,暂时 ; critical=批评的;万分紧急的; detain=阻止,拘留
    4.Now I have a bull’s-eye on my chest,just as you two.现在我也你们俩一样被人追杀
    bull’s-eye=靶心 ; chest=胸口
    5.Don’t fret now. 先不要急
    fret=(使)焦急
    6.We got ourselves a clean slate.我们都清白了
    slate=(书写用的)石板,在美语中也指"候选人名单,提名名单"
    a clean slate相当于中文里的"白纸一张,如白纸一样纯洁"
    7.Well,you were a little more formidable than we anticipated.你们比我们想像中要强大些
    formidable=强大的;令人敬畏的,可怕的
    8.We don’t need compliments out of you,jackass. 我们不需要你的恭维,混蛋
    compliments=称赞,恭维
    out of=来自;从…里面;在…范围外
    9.well,it was touch-and-go there for a minute,but i got everything handled.嗯,刚开始有点儿惊险,不过我已经掌控一切了
    touch-and-go= 草率从事的行动;一触即发的形势
    10.He is a losse end.他是个麻烦
    loose end=(常由于复数)不用的部分;未了结的零星问题
    11.you are great,top-notch.你们真强,是高手.
    (这句话是steadman在电视上看到ms和linc又逃走后,对某FBI说的 ^^)
    top大家都知道是最高的意思.notch为在一样东西上刻记号.当然最高的就是最好的,所以Top-notch是指最出众的人或其他东西. 如"top-notch personnel"即指"拔尖人才"
    12.Man,you don’t quit. 老兄,你真是执着
    13.You are smarter than a bee sting.你真聪明
    这是一个形象的比喻,bee sting为蜂刺,smart在此一语双关,以为smart既有"聪明"的意思,还有"刺痛"之意, 故于bee sting比较
    14.If anything jumps off,you get my back,I won’t forget it. 如果有事发生,你帮我一把,我不会忘记的
    jumps off的字面意思为"跳下,脱离",在文章中常表示"开始"
    15.Out there,you’re on your own. 在外面你得靠自己
    on your own=独立自主
    16.just relax and keep your head.只需放松和冷静
    keep one’s head=保持冷静
    此外,keep your head down的意思是"说话做事保持低调,不为人注意"

    第十五集
    1.Exit with your hands in the air.举手出来
    with your hands in the air=我们更熟悉的:with your hands up
    2.I’ll make you a deal if you don’t move a muscle,i won’t blow your head off.我跟你说好,只要你乖乖着.我就不打爆你的头
    not move a muscle=毫不动容,不变神色
    此外,在美国俚语中be on the muscle=准备动武; 准备蛮干
    在口语中flex one’s muscles =小试身手
    on the muscle =用暴力方式;气势汹汹的
    3.pull over. 靠边,靠岸,开到路边
    发现这是michael经常跟linc说的话—-"把车停到一边",每当linc问"why"的时候,michael都是一脸懒得跟你解释的那种神情说"just pull over"
    4.Your commitment to help others,and i put you in a place that’s every doctor’s nightmare.你承诺帮助他人,我却让你陷入医生的恶梦中
    commitment to=许诺
    5.I’m going to take a leak. 我去小解
    leak=泄漏; take a leak=小解
    6.That’s a nasty contusion.那是恶意殴打
    nasty=令人不快的;恶意的 ; contusion=殴打;打伤
    7.If you think i can pull some strings to keep you out of gen pop.I can’t do that. 如果你以为我能让你不关禁闭,那么你错了
    pull strings=在幕后操作
    gen pop是lockdown的口语说法,意为"一级防范紧闭"
    8.They’re already done irreparable damage. 他们已经造成了不可挽回的损失
    irreparable=不可挽回的 ; ir-为"不"的前缀
    reparable=可修复的,可挽回的
    9.A tape purported to be made by escaped convicts lincoln burrows and michael scofield was immediarely dismissed by the justice department.逃犯lincoln与michael做的可疑录影带被司法部门立即驳回
    purported=可疑的 (purport=意义,主旨)
    dismiss=[法律]不受理.dismiss还有"打发,解散,开除"的意思
    10.They dumped it off the front page and buried it.他们把这事从报纸头条撤下并隐瞒起来
    dump=倾倒,抛弃
    我们常在电影里听到的"He/She dumped me"的意思就是"他/她甩了我"
    front page=报纸上的头版头条,也可用"page one"
    11.It’s a hail mary,man.这是孤注一掷,老兄
    hail mary原指祷告者向圣母玛丽亚求救,而在美国口语中通常是指当成功的机率非常小时,做绝望的尝试
    12.I’m guessing they’re spoon-feeding us every lead they want us to follow.我猜他们想让我们顺着他们铺的路去白忙一场
    spoon-feeding=填鸭式
    spoon-feeding education=填鸭式教育
    13.What if this is just one giant setup?如何这是个巨大的圈套呢?
    giant=巨大的;伟大的 ; setup=陷阱,圈套
    14.I didn’t drive all this way to gloat. 我跑这么远不是来嘲笑你的
    gloat=幸灾乐祸
    15.The girl bailed on you back in Gila.这女孩在Gila都没跟你走
    我们在PB里常见的bail的用法为"保释",而bail还有个常用词义为"离开"

    第十六集
    1.Out in the cold. remember? 我被流放着,你还记得么?
    Out in the cold=被忽视,被冷落
    2.I don’t recognize the insignia, do you? 我不认识这标志?你呢?
    insignia=阶级、团体成员身份等用的佩章、衣饰等
    3.I want Scofield’s and Burrows’ pictures on each and every gas pump.我希望S和B的照片贴在每个加油站上
    gas pump=加油站
    each and every.虽然老师一直教我们each和every的区别,但从此句可以看到,口语中可用"each and every"是可以连用的,起强调作用
    4.Everything goes through headquarters from now on.从现在起,所有事都要向总部汇报
    headquarters=n.(公司,机关等的)总部,总公司;(军,警的)司令部
    headquarter=v.设立总部
    5.I need you to clear a car for me.我需要你腾出一节车厢给我
    car=火车车厢
    6.You want him to rub elbows with your other passengers?你想他和其他乘客坐一起么?
    rub=磨擦 ; elbow=肘
    rub elbows with sb.的引申义就是"与某人挨很近"
    7.Everything is jake.一切都好
    jake=(俚)对的,好
    Everything is jake=Everything is all right
    8.I tried, but your new warden, straight as an arrow.我试过了,但你们的新狱长固执得要命
    straight as an arrow=像弓箭一样直,来比喻一个人待人处世抱诚守真、刚正不阿
    eg. The man insisted that he was innocent and that he was as straight as an arrow. 那个人坚持自己是清 白的, 而且他是个正直的人
    9.And you tracked down bagwell by following susan hollander.你又通过跟踪susan hollander追捕到了bagwell.
    track down=追捕
    10.It’s just waiting to be rubber-stamped. 只需一些盖章的批准工作
    rubber-stamped=橡皮图章;照常规的批准
    11.Fowl is not part of a traditional brunch.禽肉不是传统的早午餐的一部分
    brunch=breakfast+lunch,即"早午餐"
    12.We have got company.我们有客人
    company=客人
    13.Remember that merry-go-round that we saw today? 记得我们今天看到的旋转木马么?
    merry-go-round=旋转木马
    14.what if the only thing inside’s a bunch of stogies?要里面只有一些雪茄怎么办?
    stogie=stogy=廉价的细长雪茄烟,产于宾西法尼亚(Pennsylvania)州的科内斯托加(Conestoga)
    15.I don’t wanna spend any more minutes in here than necessary.我不想再在这里浪费时间了
    …more…than necessary=比应当的更…
    16.I’m no local hayseed cop. 我不是地方草包警察
    hayseed=甘草种子,甘草屑,在美国口语中指"乡巴佬"
    17.whoever this is..tell bill kim that he just screwed up..big time.不管你是谁,告诉bill kim他这次搞砸了…砸大了
    screw up=搞糟,搞砸
    big time=[俚语]十分,极度;欢乐时刻

    第十七集
    1.she’s been ill, some chronic condition.她有病,慢性病
    chronic=(病)慢性的 ; 反之,acute=(病)急性的
    2.Find a spot close to the club and sit tight.找个离俱乐部近的地方,慢慢等着
    tight可作形容词或副词,指"牢牢的/地,不动的/地"
    3.What the hell are you thinking about, waltzing here?你到底想怎么样,还悠闲地跑到这儿?
    waltz=华尔兹,在这里指"轻松前进"
    4.She’s had this kidney thing since she was real young.她从小肾就有问题
    kidney=肾
    5.I don’t give a rat’s ass about your or your brother.我对你和你哥的事都他妈的没兴趣
    I don’t give a shit/damn/rat’s ass about sth.都算是粗口了,表示"我不在乎…"
    6.What if i’m standing on this side? 如果我处于这种情况呢?
    7.There are places that can better serve your needs.有些地方更适合你们的需要
    serve sb’s needs=help sb. (当help用腻时,可用serve sb’s needs替换)
    8.What the hell are you trying to pull.你到底想干嘛?
    pull在美国口语中指"干(勾当),耍阴谋"
    eg.Don’t try to pull anything.别想耍什么花招
    9.Look me in the eye,tell me you don’t believe there’s a cover-up going on right now.看着我的眼睛,你觉得我在欺骗你吗?
    cover-up=掩饰;掩盖
    (顺便体会一下Look me in the eye和Look at me的小区别)
    10.’cause i feel like a circus freak.因为我觉得自己像马戏团小丑
    circus=马戏团;马戏表演 ; freak=行为怪诞的人
    11.you mark my words.你牢牢记住我说的话
    mark=记下,录下,可与"remember/record"替换
    12.President reynolds attended a chicago fundraiser last night.reynolds总统昨晚在芝加哥参加了一个筹款活动
    fund=基金 ; raiser=筹措者 ; fundraiser=资金筹集活动
    13.Scofield,i don’t know what you’re used to,but anything short of filet mignon is not going to cult it with me.Scofield,我不知道你习惯怎么着,但没有一客腓力牛排别想打发我.
    short of=缺少,不足
    filet mignon=腓力牛排.这个词源于法语.意思就是牛里脊,是牛身上最贵的部分.
    14.Do you think i’d bring you here to so sacred a place to me as this if i meant you ill.如果我要害你,你觉得我会带你来这个对我来说如此神圣的地方么?
    ill用在此处指"坏的;冷酷的;恶劣的".比"bad"的程度深
    15.I am the laws of karma all come down wrong.我是因果报应的作孽的产物
    karma=命运;因果报应
    佛教中认为节制万众生灵的是所谓“功德法轮”(law of karma)此功德法轮是一组定律常规, 支配善恶的因果报应, 生命的托世轮回,.反之,
    物理的自然定律(laws of Nature), 是客观的, 是永恒的, 不受鬼神的支配的
    (由此可看出t-bag的文字功底确实了得)
    16.may need to run a few tests.可能得做些化验
    17.You don’t mind if i ask you to empty your pockets.你不介意我搜一下你的口袋吧?
    empty (out) sb’s pockets=搜查某人
    eg.The police made the thief empty out his pocket.警察搜查小偷
    此外,an empty pocket=没有钱的人.

    Previous Page Next Page

    Random Posts Recent Comments

    • Nouramohsen88 Says:

      http://goo.gl/vFWge لدينا ثلاجات عرض جديدة ومستعملة للبيع ولدينا ثلاجات عرض سوبر ماركت وحلويات في ست...

    • Nouramohsen88 Says:

      http://www.drdrahem.com/home دكتور رجيم دكتور تخسيس الكرش والارداف مركز تخسيس في مدينة نصر ...

    • Nouramohsen88 Says:

      شركه تصنيع صاعق ناموس http://www.grandelectronic-eg.com/...

    • Nouramohsen88 Says:

      شركة كشافات اضاءة في مصر http://www.grandelectronic-eg.com/ ...

    • Nouramohsen88 Says:

      http://www.grandelectronic-eg.com/ شركة كشافات طواريء في مصر...

    • Nouramohsen88 Says:

      anti-mosquitocompany.blogspot.com شركة جراند الكترونيك هي شركة مصرية متخصصة في تصنيع الكشافات الكهرب...

    • Nouramohsen88 Says:

      insect--killer.blogspot.com شركة جراند الكترونيك هي شركة مصرية متخصصة في تصنيع الكشافات الكهربية وك...

    • Nouramohsen88 Says:

      http://genius-square.com/ شركه للتدريب والاستشارات | متخصصون في التنمية البشرية...

    • Er Says:

      我了个去,我也是用的phpo ..... 看来大家的思绪差不多。。。。...

    • Fasf Says:

      SYM_TYPE * pType;改为SYM_TYPE pType;...

    Tag Cloud

    arm audio blog brew cache class debug flash google html j2me java javascript Joke linux lua mobile mtk php python ror ruby server shell stream unix web windows 优化 动态加载 女人 女生 平台 开发 手机 技术 流媒体 测试 漫画 生活 男人 男生 缓存 芯片