1. Trang chủ
  2. » Kỹ Năng Mềm

reversing secrets of reverse engineering phần 7 ppsx

62 312 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 62
Dung lượng 1,14 MB

Nội dung

The disadvantage of all of these tricks is that they count on the disassembler being relatively dumb. Luckily, most Windows disassemblers are dumb enough that you can fool them. What would happen if you ran into a clever disassembler that actually analyzes each line of code and traces the flow of data? Such a disassembler would not fall for any of these tricks, because it would detect your opaque predicate; how difficult is it to figure out that a con- ditional jump that is taken when 2 equals 3 is never actually going to be taken? Moreover, a simple data-flow analysis would expose the fact that the final JMP sequence is essentially equivalent to a JMP After, which would probably be enough to correct the disassembly anyhow. Still even a cleverer disassembler could be easily fooled by exporting the real jump addresses into a central, runtime generated data structure. It would be borderline impossible to perform a global data-flow analysis so compre- hensive that it would be able to find the real addresses without actually run- ning the program. Applications Let’s see how one would use the previous techniques in a real program. I’ve created a simple macro called OBFUSCATE, which adds a little assembly lan- guage sequence to a C program (see Listing 10.1). This sequence would tem- porarily confuse most disassemblers until they resynchronized. The number of instructions it will take to resynchronize depends not only on the specific disassembler used, but also on the specific code that comes after the macro. #define paste(a, b) a##b #define pastesymbols(a, b) paste(a, b) #define OBFUSCATE() \ _asm { mov eax, __LINE__ * 0x635186f1 };\ _asm { cmp eax, __LINE__ * 0x9cb16d48 };\ _asm { je pastesymbols(Junk,__LINE__) };\ _asm { mov eax, pastesymbols(After, __LINE__) };\ _asm { jmp eax };\ _asm { pastesymbols(Junk, __LINE__): };\ _asm { _emit (0xd8 + __LINE__ % 8) };\ _asm { pastesymbols(After, __LINE__): }; Listing 10.1 A simple code obfuscation macro that aims at confusing disassemblers. This macro was tested on the Microsoft C/C++ compiler (version 13), and contains pseudorandom values to make it slightly more difficult to search and replace (the MOV and CMP instructions and the junk byte itself are all random, calculated using the current code line number). Notice that the junk byte ranges from D8 to DF—these are good opcodes to use because they are all Antireversing Techniques 343 16_574817 ch10.qxd 3/16/05 8:44 PM Page 343 multibyte opcodes. I’m using the __LINE__ macro in order to create unique symbol names in case the macro is used repeatedly in the same function. Each occurrence of the macro will define symbols with different names. The paste and pastesymbols macros are required because otherwise the compiler just won’t properly resolve the __LINE__ constant and will use the string __LINE__ instead. If distributed throughout the code, this macro (and you could very easily create dozens of similar variations) would make the reversing process slightly more tedious. The problem is that too many copies of this code would make the program run significantly slower (especially if the macro is placed inside key loops in the program that run many times). Overusing this technique would also make the program significantly larger in terms of both memory consumption and disk space usage. It’s important to realize that all of these techniques are limited in their effec- tiveness. They most certainly won’t deter an experienced and determined reverser from reversing or cracking your application, but they might compli- cate the process somewhat. The manual approach for dealing with this kind of obfuscated code is to tell the disassembler where the code really starts. Advanced disassemblers such as IDA Pro or even OllyDbg’s built-in disas- sembler allow users to add disassembly hints, which enable the program to properly interpret the code. The biggest problem with these macros is that they are repetitive, which makes them exceedingly vulnerable to automated tools that just search and destroy them. A dedicated attacker can usually write a program or script that would eliminate them in 20 minutes. Additionally, specific disassemblers have been created that overcome most of these obfuscation techniques (see “Static Disassembly of Obfuscated Binaries” by Christopher Kruegel, et al. [Kruegel]). Is it worth it? In some cases it might be, but if you are looking for powerful antireversing techniques, you should probably stick to the control flow and data-flow obfuscating transformations discussed next. Code Obfuscation You probably noticed that the antireversing techniques described so far are all platform-specific “tricks” that in my opinion do nothing more than increase the attacker’s “annoyance factor”. Real code obfuscation involves transforming the code in such a way that makes it significantly less human-readable, while still retaining its functionality. These are typically non-platform-specific transfor- mations that modify the code to hide its original purpose and drown the reverser in a sea of irrelevant information. The level of complexity added by an obfuscating transformation is typically called potency, and can be measured using conventional software complexity metrics such as how many predicates the program contains and the depth of nesting in a particular code sequence. 344 Chapter 10 16_574817 ch10.qxd 3/16/05 8:44 PM Page 344 Beyond the mere additional complexity introduced by adding additional logic and arithmetic to a program, an obfuscating transformation must be resilient (meaning that it cannot be easily undone). Because many of these trans- formations add irrelevant instructions that don’t really produce valuable data, it is possible to create deobfuscators. A deobfuscator is a program that imple- ments various data-flow analysis algorithms on an obfuscated program which sometimes enable it to separate the wheat from the chaff and automatically remove all irrelevant instructions and restore the code’s original structure. Cre- ating resilient obfuscation transformations that are resistant to deobfuscation is a major challenge and is the primary goal of many obfuscators. Finally, an obfuscating transformation will typically have an associated cost. This can be in the form of larger code, slower execution times, or increased memory runtime consumption. It is important to realize that some transfor- mations do not incur any kind of runtime costs, because they involve a simple reorganization of the program that is transparent to the machine, but makes the program less human-readable. In the following sections, I will be going over the common obfuscating transformations. Most of these transformations were meant to be applied pro- grammatically by running an obfuscator on an existing program, either at the source code or the binary level. Still, many of these transformations can be applied manually, while the program is being written or afterward, before it is shipped to end users. Automatic obfuscation is obviously far more effective because it can obfuscate the entire program and not just small parts of it. Addi- tionally, automatic obfuscation is typically performed after the program is compiled, which means that the original source code is not made any less readable (as is the case when obfuscation is performed manually). Antireversing Techniques 345 OBFUSCATION TOOLS Let’s take a quick look at the existing obfuscation tools that can be used to obfuscate programs on the fly. There are quite a few bytecode obfuscators for Java and .NET, and I will be discussing and evaluating some of them in Chapter 12. As for obfuscation of native IA-32 code, there aren’t that many generic tools that process entire executables and effectively obfuscate them. One notable product that is quite powerful is EXECryptor by StrongBit Technology (www.strongbit.com). EXECryptor processes PE executables and applies a variety of obfuscating transformations on the machine code. Code obfuscated by EXECryptor really becomes significantly more difficult to reverse compared to plain IA-32 code. Another powerful technology is the StarForce suite of copy protection products, developed by StarForce Technologies (www.star-force. com). The StarForce products are more than just powerful obfuscation products: they are full-blown copy protection products that provide either hardware- based or pure software-based copy protection functionality. 16_574817 ch10.qxd 3/16/05 8:44 PM Page 345 Control Flow Transformations Control flow transformations are transformations that alter the order and flow of a program in a way that reduces its human readability. In “Manufacturing Cheap, Resilient, and Stealthy Opaque Constructs” by Christian Collberg, Clark Thomborson, and Douglas Low [Collberg1], control flow transformations are categorized as computation transformations, aggregation transformations, and order- ing transformations. Computation transformations are aimed at reducing the readability of the code by modifying the program’s original control flow structure in ways that make for a functionally equivalent program that is far more difficult to trans- late back into a high-level language. This is can be done either by removing control flow information from the program or by adding new control flow statements that complicate the program and cannot be easily translated into a high-level language. Aggregation transformations destroy the high-level structure of the pro- gram by breaking the high-level abstractions created by the programmer while the program was being written. The basic idea is to break such abstractions so that the high-level organization of the code becomes senseless. Ordering transformations are somewhat less powerful transformations that randomize (as much as possible) the order of operations in a program so that its readability is reduced. Opaque Predicates Opaque predicates are a fundamental building block for control flow transfor- mations. I’ve already introduced some trivial opaque predicates in the previous section on antidisassembling techniques. The idea is to create a logical state- ment whose outcome is constant and is known in advance. Consider, for exam- ple the statement if (x + 1 == x). This statement will obviously never be satisfied and can be used to confuse reversers and automated decompilation tools into thinking that the statement is actually a valid part of the program. With such a simple statement, it is going to be quite easy for both humans and machines to figure out that this is a false statement. The objective is to cre- ate opaque predicates that would be difficult to distinguish from the actual program code and whose behavior would be difficult to predict without actu- ally stepping into the code. The interesting thing about opaque predicates (and about several other aspects of code obfuscation as well) is that confusing an automated deobfuscator is often an entirely different problem from confusing a human reverser. Consider for example the concurrency-based opaque predicates suggested in [Collberg1]. The idea is to create one or more threads that are responsible for 346 Chapter 10 16_574817 ch10.qxd 3/16/05 8:44 PM Page 346 constantly generating new random values and storing them in a globally accessible data structure. The values stored in those data structures consis- tently adhere to simple rules (such as being lower or higher than a certain con- stant). The threads that contain the actual program code can access this global data structure and check that those values are within the expected range. It would make quite a challenge for an automated deobfuscator to figure this structure out and pinpoint such fake control flow statements. The concurrent access to the data would hugely complicate the matter for an automated deob- fuscator (though an obfuscator would probably only be aware of such concur- rency in a bytecode language such as Java). In contrast, a person would probably immediately suspect a thread that constantly generates random numbers and stores them in a global data structure. It would probably seem very fishy to a human reverser. Now consider a far simple arrangement where several bogus data members are added into an existing program data structure. These members are con- stantly accessed and modified by code that’s embedded right into the pro- gram. Those members adhere to some simple numeric rules, and the opaque predicates in the program rely on these rules. Such implementation might be relatively easy to detect for a powerful deobfuscator (depending on the spe- cific platform), but could be quite a challenge for a human reverser. Generally speaking, opaque predicates are more effective when imple- mented in lower-level machine-code programs than in higher-level bytecode program, because they are far more difficult to detect in low-level machine code. The process of automatically identifying individual data structures in a native machine-code program is quite difficult, which means that in most cases opaque predicates cannot be automatically detected or removed. That’s because performing global data-flow analysis on low-level machine code is not always simple or even possible. For reversers, the only way to deal with opaque predicates implemented on low-level native machine-code programs is to try and manually locate them by looking at the code. This is possible, but not very easy. In contrast, higher-level bytecode executables typically contain far more details regarding the specific data structures used in the program. That makes it much easier to implement data-flow analysis and write automated code that detects opaque predicates. The bottom line is that you should probably focus most of your antirevers- ing efforts on confusing the human reversers when developing in lower-level languages and on automated decompilers/deobfuscators when working with bytecode languages such as Java. For a detailed study of opaque constructs and various implementation ideas see [Collberg1] and General Method of Program Code Obfuscation by Gregory Wroblewski [Wroblewski]. Antireversing Techniques 347 16_574817 ch10.qxd 3/16/05 8:44 PM Page 347 Confusing Decompilers Because bytecode-based languages are highly detailed, there are numerous decompilers that are highly effective for decompiling bytecode executables. One of the primary design goals of most bytecode obfuscators is to confuse decompilers, so that the code cannot be easily restored to a highly detailed source code. One trick that does wonders is to modify the program binary so that the bytecode contains statements that cannot be translated back into the original high-level language. The example given in A Taxonomy of Obfuscating Transformations by Christian Collberg, Clark Thomborson, and Douglas Low [Collberg2] is the Java programming language, where the high-level language does not have the goto statement, but the Java bytecode does. This means that its possible to add goto statements into the bytecode in order to completely break the program’s flow graph, so that a decompiler cannot later reconstruct it (because it contains instructions that cannot be translated back to Java). In native processor languages such as IA-32 machine code, decompilation is such a complex and fragile process that any kind of obfuscation transforma- tion could easily get them to fail or produce meaningless code. Consider, for example, what would happen if a decompiler ran into the OBFUSCATE macro from the previous section. Table Interpretation Converting a program or a function into a table interpretation layout is a highly powerful obfuscation approach, that if done right can repel both deob- fuscators and human reversers. The idea is to break a code sequence into mul- tiple short chunks and have the code loop through a conditional code sequence that decides to which of the code sequences to jump at any given moment. This dramatically reduces the readability of the code because it com- pletely hides any kind of structure within it. Any code structures, such as log- ical statements or loops, are buried inside this unintuitive structure. As an example, consider the simple data processing function in Listing 10.2. 00401000 push esi 00401001 push edi 00401002 mov edi,dword ptr [esp+10h] 00401006 xor eax,eax 00401008 xor esi,esi 0040100A cmp edi,3 0040100D jbe 0040103A 0040100F mov edx,dword ptr [esp+0Ch] 00401013 add edi,0FFFFFFFCh 00401016 push ebx Listing 10.2 A simple data processing function that XORs a data block with a parameter passed to it and writes the result back into the data block. 348 Chapter 10 16_574817 ch10.qxd 3/16/05 8:44 PM Page 348 00401017 mov ebx,dword ptr [esp+18h] 0040101B shr edi,2 0040101E push ebp 0040101F add edi,1 00401022 mov ecx,dword ptr [edx] 00401024 mov ebp,ecx 00401026 xor ebp,esi 00401028 xor ebp,ebx 0040102A mov dword ptr [edx],ebp 0040102C xor eax,ecx 0040102E add edx,4 00401031 sub edi,1 00401034 mov esi,ecx 00401036 jne 00401022 00401038 pop ebp 00401039 pop ebx 0040103A pop edi 0040103B pop esi 0040103C ret Listing 10.2 A simple data processing function that XORs a data block with a parameter passed to it and writes the result back into the data block. Let us now take this function and transform it using a table interpretation transformation. 00401040 push ecx 00401041 mov edx,dword ptr [esp+8] 00401045 push ebx 00401046 push ebp 00401047 mov ebp,dword ptr [esp+14h] 0040104B push esi 0040104C push edi 0040104D mov edi,dword ptr [esp+10h] 00401051 xor eax,eax 00401053 xor ebx,ebx 00401055 mov ecx,1 0040105A lea ebx,[ebx] 00401060 lea esi,[ecx-1] 00401063 cmp esi,8 00401066 ja 00401060 00401068 jmp dword ptr [esi*4+4010B8h] 0040106F xor dword ptr [edx],ebx 00401071 add ecx,1 00401074 jmp 00401060 00401076 mov edi,dword ptr [edx] Listing 10.3 The data-processing function from Listing 10.2 transformed using a table interpretation transformation. (continued) Antireversing Techniques 349 16_574817 ch10.qxd 3/16/05 8:44 PM Page 349 00401078 add ecx,1 0040107B jmp 00401060 0040107D cmp ebp,3 00401080 ja 00401071 00401082 mov ecx,9 00401087 jmp 00401060 00401089 mov ebx,edi 0040108B add ecx,1 0040108E jmp 00401060 00401090 sub ebp,4 00401093 jmp 00401055 00401095 mov esi,dword ptr [esp+20h] 00401099 xor dword ptr [edx],esi 0040109B add ecx,1 0040109E jmp 00401060 004010A0 xor eax,edi 004010A2 add ecx,1 004010A5 jmp 00401060 004010A7 add edx,4 004010AA add ecx,1 004010AD jmp 00401060 004010AF pop edi 004010B0 pop esi 004010B1 pop ebp 004010B2 pop ebx 004010B3 pop ecx 004010B4 ret The function’s jump table: 0x004010B8 0040107d 00401076 00401095 0040106f 0x004010C8 00401089 004010a0 004010a7 00401090 0x004010D8 004010af Listing 10.3 (continued) The function in Listing 10.3 is functionally equivalent to the one in 10.2, but it was obfuscated using a table interpretation transformation. The function was broken down into nine segments that represent the different stages in the original function. The implementation constantly loops through a junction that decides where to go next, depending on the value of ECX. Each code seg- ment sets the value of ECX so that the correct code segment follows. The spe- cific code address that is executed is determined using the jump table, which is included at the end of the listing. Internally, this is implemented using a sim- ple switch statement, but when you think of it logically, this is similar to a lit- tle virtual machine that was built just for this particular function. Each “instruction” advances the “instruction pointer”, which is stored in ECX. The actual “code” is the jump table, because that’s where the sequence of opera- tions is stored. 350 Chapter 10 16_574817 ch10.qxd 3/16/05 8:44 PM Page 350 This transformation can be improved upon in several different ways, depending on how much performance and code size you’re willing to give up. In a native code environment such as IA-32 assembly language, it might be beneficial to add some kind of disassembler-confusion macros such as the ones described earlier in this chapter. If made reasonably polymorphic, such macros would not be trivial to remove, and would really complicate the reversing process for this kind of a function. That’s because these macros would prevent reversers from being able to generate a full listing of the obfuscated at any given moment. Reversing a table interpretation function such as the one in Listing 10.3 without having a full view of the entire function is undoubtedly an unpleasant reversing task. Other than the confusion macros, another powerful enhancement for the obfuscation of the preceding function would be to add an additional lookup table, as is demonstrated in Listing 10.4. 00401040 sub esp,28h 00401043 mov edx,dword ptr [esp+2Ch] 00401047 push ebx 00401048 push ebp 00401049 mov ebp,dword ptr [esp+38h] 0040104D push esi 0040104E push edi 0040104F mov edi,dword ptr [esp+10h] 00401053 xor eax,eax 00401055 xor ebx,ebx 00401057 mov dword ptr [esp+14h],1 0040105F mov dword ptr [esp+18h],8 00401067 mov dword ptr [esp+1Ch],4 0040106F mov dword ptr [esp+20h],6 00401077 mov dword ptr [esp+24h],2 0040107F mov dword ptr [esp+28h],9 00401087 mov dword ptr [esp+2Ch],3 0040108F mov dword ptr [esp+30h],7 00401097 mov dword ptr [esp+34h],5 0040109F lea ecx,[esp+14h] 004010A3 mov esi,dword ptr [ecx] 004010A5 add esi,0FFFFFFFFh 004010A8 cmp esi,8 004010AB ja 004010A3 004010AD jmp dword ptr [esi*4+401100h] 004010B4 xor dword ptr [edx],ebx 004010B6 add ecx,18h 004010B9 jmp 004010A3 004010BB mov edi,dword ptr [edx] 004010BD add ecx,8 004010C0 jmp 004010A3 Listing 10.4 The data-processing function from Listing 10.2 transformed using an array- based version of the table interpretation obfuscation method. (continued) Antireversing Techniques 351 16_574817 ch10.qxd 3/16/05 8:44 PM Page 351 004010C2 cmp ebp,3 004010C5 ja 004010E8 004010C7 add ecx,14h 004010CA jmp 004010A3 004010CC mov ebx,edi 004010CE sub ecx,14h 004010D1 jmp 004010A3 004010D3 sub ebp,4 004010D6 sub ecx,4 004010D9 jmp 004010A3 004010DB mov esi,dword ptr [esp+44h] 004010DF xor dword ptr [edx],esi 004010E1 sub ecx,10h 004010E4 jmp 004010A3 004010E6 xor eax,edi 004010E8 add ecx,10h 004010EB jmp 004010A3 004010ED add edx,4 004010F0 sub ecx,18h 004010F3 jmp 004010A3 004010F5 pop edi 004010F6 pop esi 004010F7 pop ebp 004010F8 pop ebx 004010F9 add esp,28h 004010FC ret The function’s jump table: 0x00401100 004010c2 004010bb 004010db 004010b4 0x00401110 004010cc 004010e6 004010ed 004010d3 0x00401120 004010f5 Listing 10.4 (continued) The function in Listing 10.4 is an enhanced version of the function from List- ing 10.3. Instead of using direct indexes into the jump table, this implementa- tion uses an additional table that is filled in runtime. This table contains the actual jump table indexes, and the index into that table is handled by the pro- gram in order to obtain the correct flow of the code. This enhancement makes this function significantly more unreadable to human reversers, and would also seriously complicate matters for a deobfuscator because it would require some serious data-flow analysis to determine the current value of the index to the array. The original implementation in [Wang] is more focused on preventing static analysis of the code by deobfuscators. The approach chosen in that study is to use pointer aliases as a means of confusing automated deobfuscators. Pointer aliases are simply multiple pointers that point to the same memory location. Aliases significantly complicate any kind of data-flow analysis process 352 Chapter 10 16_574817 ch10.qxd 3/16/05 8:44 PM Page 352 [...]... h 477 w81 This doesn’t mean that the program doesn’t have any code, it simply means that the code is most likely tucked in one of those oddly named sections At this point it would be wise to run DUMPBIN with the /HEADERS option to get a better idea of how Defender is built (see Listing 11.5) Microsoft (R) COFF/PE Dumper Version 7. 10.3 077 Copyright (C) Microsoft Corporation All rights reserved Dump of. .. reserve 1000 size of heap commit 0 loader flags 10 number of directories 5060 [ 35] RVA [size] of Export Directory 5008 [ 28] RVA [size] of Import Directory 0 [ 0] RVA [size] of Resource Directory 0 [ 0] RVA [size] of Exception Directory 0 [ 0] RVA [size] of Certificates Directory 0 [ 0] RVA [size] of Base Relocation Directory 0 [ 0] RVA [size] of Debug Directory 0 [ 0] RVA [size] of Architecture Directory... Read Write SECTION HEADER #4 h 477 w81 name 8C virtual size 70 00 virtual address (004 070 00 to 004 070 8B) 200 size of raw data 3A00 file pointer to raw data (00003A00 to 00003BFF) 0 file pointer to relocation table 0 file pointer to line numbers 0 number of relocations 0 number of line numbers C0000040 flags Initialized Data Read Write Summary 1000 4000 1000 1000 data h3mf85n h 477 w81 rdata Listing 11.5 (continued)... (continued) 373 374 Chapter 11 4 4129382F 0 0 E0 10F number of sections time date stamp Mon Aug 23 03:19:59 2004 file pointer to symbol table number of symbols size of optional header characteristics Relocations stripped Executable Line numbers stripped Symbols stripped 32 bit word machine OPTIONAL HEADER VALUES 10B magic # (PE32) 7. 10 linker version 3400 size of code 600 size of initialized data 0 size of uninitialized... Microsoft (R) COFF/PE Dumper Version 7. 10.3 077 Copyright (C) Microsoft Corporation All rights reserved Dump of file defender.exe Listing 11.4 Output from DUMPBIN when run on Defender.EXE with the /IMPORTS option Breaking Protections File Type: EXECUTABLE IMAGE Section contains the following imports: KERNEL32.dll 405000 405030 0 0 Import Address Table Import Name Table time date stamp Index of first... RVA [size] of Debug Directory 0 [ 0] RVA [size] of Architecture Directory 0 [ 0] RVA [size] of Global Pointer Directory Listing 11.5 (continued) Breaking Protections 0 0 0 5000 0 0 0 [ [ [ [ [ [ [ 0] 0] 0] 8] 0] 0] 0] RVA RVA RVA RVA RVA RVA RVA [size] [size] [size] [size] [size] [size] [size] of of of of of of of Thread Storage Directory Load Configuration Directory Bound Import Directory Import Address... base of code 5000 base of data 400000 image base (00400000 to 00407FFF) 1000 section alignment 200 file alignment 4.00 operating system version 0.00 image version 4.00 subsystem version 0 Win32 version 8000 size of image 400 size of headers 0 checksum 3 subsystem (Windows CUI) 400 DLL characteristics No safe exception handler 100000 size of stack reserve 1000 size of stack commit 100000 size of heap... h3mf85n:0040426E h3mf85n:00404 271 h3mf85n:00404 273 h3mf85n:00404 278 h3mf85n:0040427D h3mf85n:0040427F h3mf85n:00404281 h3mf85n:00404283 h3mf85n:00404283 h3mf85n:00404283 h3mf85n:00404283 h3mf85n:00404286 h3mf85n:0040428C h3mf85n:0040428E h3mf85n:0040428E h3mf85n:0040428E h3mf85n:0040428E h3mf85n:00404290 h3mf85n:00404292 h3mf85n:00404295 h3mf85n:004042 97 h3mf85n:004042 97 h3mf85n:004042 97 h3mf85n:00404299 h3mf85n:0040429B... calls them Instead of having all callers call into a single copy of the function, the compiler replaces every call into the function with an actual in-place copy of it This improves runtime performance because the overhead of calling a function is completely eliminated, at the cost of significantly bloating the size of the program (because functions are duplicated) In the context of obfuscating transformations,... mov ecx, eax mov eax, [eax] mov edi, 6DEF20h xor esi, esi jmp short loc_404260 ; Listing 11.6 A disassembly of Defender’s entry point function, generated by IDA (continued) 377 378 Chapter 11 h3mf85n:004042 57 h3mf85n:004042 57 h3mf85n:004042 57 h3mf85n:00404259 h3mf85n:0040425B h3mf85n:0040425E h3mf85n:00404260 h3mf85n:00404260 h3mf85n:00404260 h3mf85n:00404262 h3mf85n:00404264 . (continued) Antireversing Techniques 349 16_ 574 8 17 ch10.qxd 3/16/05 8:44 PM Page 349 00401 078 add ecx,1 0040107B jmp 00401060 0040107D cmp ebp,3 00401080 ja 00401 071 00401082 mov ecx,9 004010 87 jmp. of opaque constructs and various implementation ideas see [Collberg1] and General Method of Program Code Obfuscation by Gregory Wroblewski [Wroblewski]. Antireversing Techniques 3 47 16_ 574 8 17. encoding of some or all program variables. This can greatly confuse reversers because the intuitive Antireversing Techniques 355 16_ 574 8 17 ch10.qxd 3/16/05 8:44 PM Page 355 meaninings of variable

Ngày đăng: 14/08/2014, 11:21

TỪ KHÓA LIÊN QUAN