├── .gitignore ├── Makefile ├── README ├── SUMMARY ├── assemble.py ├── config.py ├── enc.py ├── pefile.py ├── penis.py ├── ssexy.py ├── test.sh ├── testbinaries ├── daemon │ ├── daemon.vcxproj │ ├── daemon.vcxproj.filters │ ├── daemon.vcxproj.user │ └── main.c ├── hello-world │ ├── hello-world.sln │ ├── hello-world.vcxproj │ ├── hello-world.vcxproj.filters │ ├── hello-world.vcxproj.user │ └── main.c ├── memstuff │ ├── main.cpp │ ├── memstuff.vcxproj │ ├── memstuff.vcxproj.filters │ └── memstuff.vcxproj.user ├── msgbox │ ├── main.c │ ├── msgbox.vcxproj │ ├── msgbox.vcxproj.filters │ └── msgbox.vcxproj.user ├── nc │ ├── main.c │ ├── nc.vcxproj │ ├── nc.vcxproj.filters │ └── nc.vcxproj.user ├── netcat │ ├── Makefile │ ├── doexec.c │ ├── generic.h │ ├── getopt.c │ ├── getopt.h │ ├── hobbit.txt │ ├── license.txt │ ├── netcat.c │ ├── netcat.vcxproj │ ├── netcat.vcxproj.filters │ ├── netcat.vcxproj.user │ └── readme.txt └── switch │ ├── main.c │ ├── switch.vcxproj │ ├── switch.vcxproj.filters │ └── switch.vcxproj.user ├── tests.py └── translate.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.o 3 | *.idb 4 | *.id0 5 | *.id1 6 | *.nam 7 | *.pyc 8 | testing 9 | testing.cpp -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | python penis.py yasm.exe 3 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | SSEXY - Convert x86 Instruction into their SSE equivalent. 2 | For more information; read the slides and summary which can be found here. 3 | http://jbremer.org/ssexy.zip 4 | -------------------------------------------------------------------------------- /SUMMARY: -------------------------------------------------------------------------------- 1 | SSEXY (C) jbremer, Jurriaan Bremer 2012 2 | 3 | Introduction 4 | 5 | Over the past few decades people have been Reverse Engineering binaries in 6 | order to understand what they do, how they do it, and to find vulnerabilities. 7 | 8 | In order to protect these binaries from third party reverse engineers, a lot 9 | of research has been done regarding the obfuscation of binaries and their 10 | internals. 11 | 12 | In this presentation I will present an obfuscation based on x86 instructions 13 | (these instructions represent everything the binary does, e.g. print a value 14 | to the command line, calculate the length of a string, etc.) 15 | 16 | Note that, by using obfuscation, it becomes harder to analyze a binary, and 17 | therefore, it tries to keep attackers away from analyzing the binary. Thus 18 | making it less likely that your favourite private algorithm will be exposed, 19 | and/or vulnerabilities located. 20 | 21 | Current Approaches 22 | 23 | Several techniques are being used in the wild which aid in obfuscation. 24 | These include the following approaches: 25 | 26 | - Virtual Machines; 27 | translate x86 into a custom instruction set, this forces a Reverse 28 | Engineer to learn the new instruction set, which is time consuming. 29 | 30 | - Metamorphic Engines; 31 | rewrite an instruction to do the same, but with another 32 | representation, i.e. one instruction might be converted to 10 other 33 | instructions which result in the exact same output. 34 | 35 | - Polymorphic Engines; 36 | encrypt the byte code of the instructions (the representation of x86 37 | instructions in a way that the CPU understands them) and decrypt them 38 | runtime, usually this is done by bruteforcing the key. 39 | 40 | What is SSE 41 | 42 | SSE is an acronym for "Streaming SIMD Extensions", SIMD being "Single 43 | Instruction, Multiple Data". Basically SSE is an extra Instruction Set on top of 44 | the "regular" x86 instructions, it was made for vector math, to enhance speed in 45 | 3D gaming engines etc, although it can (obviously) be used for anything. 46 | 47 | So what does this mean? There are more instructions than used in regular 48 | binaries, this means that, as it is barely used, people are unfamiliar with the 49 | SSE instruction set. We can use this to our advantage by transforming regular 50 | instructions to an equivalent in SSE, therefore obfuscating the execution flow. 51 | 52 | Note: Since some of the SSE instruction sets are relatively new (4.1, 4.2 and 53 | 5.0) they might not work on somewhat older CPUs, hence I only use instructions 54 | from SSE and SSE2, which are supported since the Pentium 3 and 4 respectively, 55 | so that should run on any modern computer. 56 | 57 | How does SSE work 58 | 59 | SSE introduces dozens of new instructions to the existing x86 instruction set, 60 | fortunately for me there are many semi-overlapping instructions (ie: there is an 61 | add instruction in both x86 and SSE.) Due to this, almost all x86 instructions 62 | can be translated into their SSE equivalent. 63 | 64 | One could see SSE as a complete instruction set on it's own, if you omit a few 65 | key features (such as branching.) This also means that SSE instructions operate 66 | on their own registers, SSE has 8 XMM register and the best part of this is, 67 | they are 128bit (16 bytes) in length. That's right, we can store four 32bit 68 | integers in just one XMM register, I take advantage of this, as you will see 69 | later on. 70 | 71 | Other than that, SSE also has a few instructions to "communicate" with "normal 72 | x86 instructions", for example one can load the lowest 32bits of an XMM register 73 | from a GPR (General Purpose Register, x86's registers) and store the lowest 74 | 32bits of an XMM register into a GPR. Besides that the entire 128bits can be 75 | stored to / loaded from an address that you can specify with GPRs. 76 | 77 | What does SSEXY do 78 | 79 | So this SSEXY tool translates "regular" x86 assembly into SSE instructions, but 80 | how does that work? So there are 8 GPRs, these are 32bit 81 | registers that store stuff like intermediate values, stack pointers, return 82 | values etc. But that's nice, 8 registers * 32 bits = 256 bits, this means 83 | we can store all GPRs in just two XMM registers. So basically we emulate the 84 | "normal" x86 instructions using SSE instructions. 85 | 86 | Storing the GPRs as 32bit integers in XMM registers means that for every opcode 87 | we will have to extract the values from the XMM registers and operate on them 88 | from there, this gives us quite some overhead, but then again, this tool is not 89 | made to decrease speed in execution time in existing binaries. 90 | 91 | There are a few pitfalls, but almost all commonly (!) used instructions are 92 | relatively easy to implement in SSE. For example, a lot of x86 instructions 93 | (such as addition and subtracting instructions) set conditional flags which can 94 | be used to jump somewhere else in the code, this is a bit harder to emulate in 95 | SSE, but still doable. 96 | 97 | Overlap Existing Techniques 98 | 99 | It may or may not have occurred to the reader that SSEXY is basically a new 100 | way of obfuscation, introducing a combination of techniques from Virtual 101 | Machines and Metamorphic Engines. This makes SSEXY very powerful, 102 | obfuscation-wise. 103 | 104 | Tests 105 | 106 | For my first presentation, at the Hack in the Box conference, I have developed 107 | an initial version of SSEXY. This was merely to demonstrate the Proof of 108 | Concept, and it's very, very limited. However, the results were already fairly 109 | nice, e.g. IDA Pro simply fails to recognize all instructions, not to mention 110 | graph view, or displaying basic blocks. 111 | 112 | The existing presentation and sample binary can be found here; 113 | http://jbremer.org/ssexy.zip 114 | 115 | However, if accepted, I will develop the tool further. The idea is that it 116 | should be able to handle a normal binary, i.e. any binary that was just 117 | compiled and doesn't contain any weird stuff (such as embedded shellcode.) 118 | 119 | Cool stuff 120 | 121 | A few observations, which make this tool (and research) interesting, in my 122 | opinion: 123 | 124 | - Static Analyzers break: they, most likely, lack support for SSE instructions 125 | 126 | - Reverse Engineers will have headaches: "new" instruction set, there are no 127 | tools to automate processing it *yet* (see point 1), this extends the time 128 | it takes to analyze such binary 129 | 130 | - Anti-Virus engines will fail: static analysis will most likely fail. 131 | 132 | - (Potentially) defeating ROP exploits; I will talk about exploitability of a 133 | binary using the well-known ROP gadgets, if I'm not mistaken, ROP exploits 134 | will be a lot harder, but I'm not 100% sure about that yet. 135 | 136 | Improvements 137 | 138 | Several improvements, on top of the "basic" features, include: 139 | 140 | - Optimalizing instruction implementations; reducing amount of SSE 141 | instructions needed per x86 instruction (i.e. removing dead code) 142 | 143 | - Shuffling the GPRs stored in XMM registers to obfuscate a bit 144 | 145 | - Simple "encryption" of the GPRs stored in XMM registers (or even using 146 | different encryption keys depending on the function we are currently in, 147 | function as in a function in the C programming language) 148 | 149 | - Combining several x86 instructions into a series of SSE instructions 150 | 151 | - ... Whatever floats your boat ... 152 | 153 | Conclusion 154 | 155 | I have proposed a relatively new way to obfuscate existing binaries and, 156 | hopefully, a new way to fool Reverse Engineers, static analyzers and Anti Virus 157 | engines. 158 | 159 | Jurriaan Bremer, jbremer, jurriaanbremer@gmail.com 160 | -------------------------------------------------------------------------------- /assemble.py: -------------------------------------------------------------------------------- 1 | import os, struct, distorm3 2 | from ctypes import * 3 | 4 | WAIT_TIMEOUT = 0x102 5 | 6 | CONTEXT_X86 = 0x00010000 7 | CONTEXT_CONTROL = CONTEXT_X86 | 0x1L # SS:SP, CS:IP, FLAGS, BP 8 | CONTEXT_INTEGER = CONTEXT_X86 | 0x2L # AX, BX, CX, DX, SI, DI 9 | CONTEXT_SEGMENTS = CONTEXT_X86 | 0x4L # DS, ES, FS, GS 10 | CONTEXT_FLOATING_POINT = CONTEXT_X86 | 0x8L # 387 state 11 | CONTEXT_DEBUG_REGISTERS = CONTEXT_X86 | 0x10L # DB 0-3,6,7 12 | CONTEXT_EXTENDED_REGISTERS = CONTEXT_X86 | 0x20L # cpu specific extensions 13 | CONTEXT_FULL = CONTEXT_CONTROL | CONTEXT_INTEGER | \ 14 | CONTEXT_SEGMENTS 15 | 16 | EAX = 0 17 | ECX = 1 18 | EDX = 2 19 | EBX = 3 20 | ESP = 4 21 | EBP = 5 22 | ESI = 6 23 | EDI = 7 24 | 25 | kernel32 = windll.kernel32 26 | msvcrt = cdll.msvcrt 27 | 28 | def assemble(lines, fname): 29 | lines.insert(0, 'bits 32') 30 | lines.insert(1, 'org 0xfed0000') 31 | file('%s.asm' % fname, 'w').write('\n'.join(lines)) 32 | os.system('yasm -mx86 %s.asm -o%s' % (fname, fname)) 33 | ret = open(fname, 'rb').read() 34 | os.unlink('%s.asm' % fname) 35 | os.unlink(fname) 36 | return ret 37 | 38 | class _CONTEXT(Structure): 39 | _fields_ = [ 40 | ('ContextFlags', c_uint), 41 | ('Unused0', c_char * 180), 42 | ('Eip', c_uint), 43 | ('Unused1', c_char * (16 + 0xa0)), 44 | ('Xmm', c_uint * 32), 45 | ('Unused2', c_char * (512-0xa0)) 46 | ] 47 | 48 | class _Stack(Structure): 49 | _fields_ = [ 50 | ('Mem', c_uint * 4) 51 | ] 52 | 53 | class Debuggable: 54 | def __init__(self, machine_code, stack, code): 55 | # copy of the raw machine code we have to process 56 | self.machine_code = machine_code 57 | 58 | # memory for our real machine code 59 | self.code = code 60 | 61 | # stack of our stuff 62 | self.stack = stack 63 | 64 | # list of instructions and m128s, for debugging purposes 65 | self.instructions = [] 66 | self.m128s = {} 67 | 68 | def _run(self, machine_code, verbose = False): 69 | # copy the buffer directly to memory 70 | msvcrt.memcpy(self.code, byref(create_string_buffer(machine_code)), \ 71 | len(machine_code)) 72 | 73 | # clean the stack.. :) that is, zero it out. 74 | kernel32.WriteProcessMemory(-1, self.stack, byref(_Stack()), 16, None) 75 | 76 | # create new thread 77 | hThread = kernel32.CreateThread(None, None, self.code, None, None, None) 78 | 79 | # initialize the instructions variabele 80 | index = 0 ; self.instructions.append('RETN') 81 | lastEip = None 82 | lastXmm = [0 for i in xrange(32)] 83 | lastMem = [0 for i in xrange(4)] 84 | 85 | # give it one millisecond to execute the following instruction.. 86 | while kernel32.WaitForSingleObject(hThread, 1) == WAIT_TIMEOUT: 87 | context = _CONTEXT() 88 | stack = _Stack() 89 | 90 | context.ContextFlags = CONTEXT_FULL | CONTEXT_EXTENDED_REGISTERS 91 | kernel32.SuspendThread(hThread) 92 | kernel32.GetThreadContext(hThread, byref(context)) 93 | 94 | # eip is not in our code section, let's just continue 95 | if context.Eip < self.code or context.Eip > self.code + \ 96 | len(machine_code): 97 | kernel32.ResumeThread(hThread) 98 | continue 99 | 100 | # read the stack memory here (so it also works in non-verbose mode) 101 | kernel32.ReadProcessMemory(-1, self.stack, byref(stack), 16, None) 102 | 103 | # if eip didn't change yet or eip is not even in 104 | # our code section yet, continue.. 105 | if context.Eip == lastEip: 106 | kernel32.ResumeThread(hThread) 107 | continue 108 | 109 | # print the xmm registers and the stack memory 110 | if verbose: 111 | # print the xmm registers that will be altered by this 112 | # instruction before the instruction 113 | for i in xrange(8): 114 | if context.Xmm[i*4:i*4+4] != lastXmm[i*4:i*4+4]: 115 | print 'xmm%d 0x%08x 0x%08x 0x%08x 0x%08x' % \ 116 | tuple([i] + lastXmm[i*4:i*4+4]) 117 | 118 | # print the instruction (with possibly the m128 referenced) 119 | print '0x%08x: %s' % (0xfed0000 + context.Eip - self.code, \ 120 | self.instructions[index]) 121 | 122 | # print the xmm registers after the instructions 123 | for i in xrange(8): 124 | if context.Xmm[i*4:i*4+4] != lastXmm[i*4:i*4+4]: 125 | print 'xmm%d 0x%08x 0x%08x 0x%08x 0x%08x' % \ 126 | tuple([i] + context.Xmm[i*4:i*4+4]) 127 | lastXmm = context.Xmm 128 | 129 | # TODO: Come up with a better way to read the stack memory 130 | if lastMem != list(stack.Mem): 131 | print 'stack', ' '.join(map(lambda x: '0x%08x' % x, \ 132 | stack.Mem)) 133 | lastMem = list(stack.Mem) 134 | 135 | print '' # newline 136 | 137 | # store the last eip 138 | lastEip = context.Eip 139 | 140 | # skip the while(1) loop 141 | context.Eip += 2 142 | index += 1 143 | 144 | # continue the debugging stuff 145 | kernel32.SetThreadContext(hThread, byref(context)) 146 | kernel32.ResumeThread(hThread) 147 | 148 | # close our thread handle 149 | kernel32.CloseHandle(hThread) 150 | 151 | # return the Xmm registers and memory registers 152 | return ''.join(map(lambda x: struct.pack('L', x), \ 153 | list(context.Xmm) + list(stack.Mem))) 154 | 155 | def debug(self): 156 | # disasm the machine code, to obtain each instruction 157 | # so we can place a while(1) between them 158 | buf = '' ; offset = 0 ; addr = {} 159 | while offset != len(self.machine_code): 160 | instr = distorm3.Decompose(None, self.machine_code[offset:])[0] 161 | hexdump = instr.instructionBytes.encode('hex') 162 | 163 | # increase offset 164 | offset += len(hexdump) / 2 165 | 166 | # short jmp, we have to skip this.. (16-byte aligned m128) 167 | if hexdump[:2] == 'eb': 168 | # calculate the jmp-length 169 | jmp_len = int(hexdump[2:], 16) 170 | 171 | # extract the m128 172 | m128 = self.machine_code[offset+jmp_len-16:offset+jmp_len] 173 | 174 | # align to 16 bytes and write the m128 (including jmp over it) 175 | # 32 bytes = 30 bytes align + 2 bytes short jmp 176 | buf += '90'*(30 - (len(buf)/2 % 16)) + \ 177 | 'eb10' + m128.encode('hex') 178 | 179 | # write this addr in our dictionary 180 | addr[0xfed0000+offset+jmp_len-16] = self.code + len(buf)/2 - 16 181 | 182 | # keep a dictionary with address -> m128 183 | self.m128s[0xfed0000+offset+jmp_len-16] = \ 184 | struct.unpack('4L', m128) 185 | 186 | offset += jmp_len 187 | # normal and sse instructions are followed by a while(1) loop 188 | else: 189 | buf += hexdump + 'ebfe' 190 | 191 | # if referenced, display m128 as well 192 | m128 = '' 193 | if instr.operands[1].type == distorm3.OPERAND_ABSOLUTE_ADDRESS: 194 | m128 = '\nm128 ' + ' '.join(map(lambda x: '0x%08x' % x, \ 195 | self.m128s[instr.operands[1].disp])) 196 | 197 | self.instructions.append(str(instr).lower() + m128) 198 | 199 | # replace all old addresses with new addresses, using a sortof bad way 200 | for key, value in addr.items(): 201 | buf = buf.replace(struct.pack('L', key).encode('hex'), \ 202 | struct.pack('L', value).encode('hex')) 203 | 204 | # exit the thread after a last while(1) loop, 205 | # to get the final xmm registers 206 | buf += 'ebfec3' 207 | 208 | return self._run(buf.decode('hex'), True) 209 | 210 | def run(self): 211 | # i hope for the sake of simplicity that 0xfed is 212 | # quite unlikely, in normal assembly.. 213 | code = self.machine_code.replace(struct.pack('H', 0xfed), \ 214 | struct.pack('H', self.code >> 16)) 215 | return self._run(code + '\xeb\xfe\xc3') 216 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Configuration file for ssexy. 4 | 5 | """ 6 | 7 | class Api: 8 | def __init__(self, name, resets=False): 9 | """Define a new API. 10 | 11 | `name' is the name when linking. 12 | `resets' indicates if this API resets Xmm Registers, if so, 13 | registers should be stored temporarily. 14 | 15 | """ 16 | self.name = name 17 | self.resets = resets 18 | 19 | def __str__(self): 20 | return self.name 21 | 22 | apis = [ 23 | ('SetUnhandledExceptionFilter', '_SetUnhandledExceptionFilter@4'), 24 | ('MessageBoxA', '_MessageBoxA@16', True), 25 | (('ws2_32.dll', 1), '_accept@12'), 26 | (('ws2_32.dll', 2), '_bind@12'), 27 | (('ws2_32.dll', 3), '_closesocket@4'), 28 | (('ws2_32.dll', 5), '_getpeername@12'), 29 | (('ws2_32.dll', 9), '_htons@4'), 30 | (('ws2_32.dll', 0x0c), '_inet_ntoa@4'), 31 | (('ws2_32.dll', 0x0d), '_listen@8'), 32 | (('ws2_32.dll', 0x10), '_recv@16'), 33 | (('ws2_32.dll', 0x17), '_socket@12'), 34 | (('ws2_32.dll', 0x73), '_WSAStartup@8'), 35 | ] 36 | 37 | # convert each definition to an Api instance. 38 | apis = dict([(x[0], Api(*x[1:])) for x in apis]) 39 | -------------------------------------------------------------------------------- /enc.py: -------------------------------------------------------------------------------- 1 | import sys, binascii, assemble, distorm3 2 | from distorm3 import OPERAND_REGISTER, OPERAND_IMMEDIATE, OPERAND_MEMORY, \ 3 | OPERAND_ABSOLUTE_ADDRESS 4 | 5 | def enc_apply(hex): 6 | dec = distorm3.Decompose(0, hex.decode('hex'), distorm3.Decode32Bits) 7 | return Enc(dec[0]).encode() 8 | 9 | class Enc: 10 | _labels = {} 11 | _ff_flag = {8: 0xff, 16: 0xffff, 32: 0xffffffff} 12 | 13 | def __init__(self, dis): 14 | if not dis: return 15 | self.dis = dis 16 | self.reg_index1 = None 17 | self.reg_index2 = None 18 | self.xmm_index1 = None 19 | self.xmm_index2 = None 20 | self.xmm_reg1 = None 21 | self.xmm_reg2 = None 22 | self.lines = [] 23 | 24 | if len(dis.operands) > 0: 25 | self.type1 = dis.operands[0].type 26 | if self.type1 == OPERAND_REGISTER: 27 | self.reg_index1 = dis.operands[0].index & 7 28 | self.xmm_index1 = dis.operands[0].index & 3 29 | self.xmm_reg1 = self._xmm_gpr_index(self.reg_index1) 30 | self.size1 = self.dis.operands[0].size 31 | elif self.type1 == OPERAND_IMMEDIATE: 32 | self.imm1 = self.dis.operands[0].value 33 | elif self.type1 == OPERAND_ABSOLUTE_ADDRESS: 34 | self.type1 = OPERAND_MEMORY 35 | 36 | if len(dis.operands) > 1: 37 | self.type2 = dis.operands[1].type 38 | if self.type2 == OPERAND_REGISTER: 39 | self.reg_index2 = dis.operands[1].index & 7 40 | self.xmm_index2 = dis.operands[1].index & 3 41 | self.xmm_reg2 = self._xmm_gpr_index(self.reg_index2) 42 | self.size2 = self.dis.operands[1].size 43 | elif self.type2 == OPERAND_IMMEDIATE: 44 | self.imm2 = self.dis.operands[1].value 45 | elif self.type2 == OPERAND_ABSOLUTE_ADDRESS: 46 | self.type2 = OPERAND_MEMORY 47 | 48 | # reset labels dict 49 | def reset_labels(self): 50 | Enc._labels = {} 51 | 52 | def encode(self): 53 | func = getattr(self, '_encode_' + self.dis.mnemonic.lower(), None) 54 | if not func: 55 | raise Exception('Cannot encode %s' % self.dis.mnemonic.lower()) 56 | func() 57 | return self.lines 58 | 59 | # find register for gpr 60 | def _xmm_gpr_index(self, gpr_index): 61 | return 'xmm%d' % (6 + gpr_index / 4) 62 | 63 | # construct a 16byte xmm value 64 | def _m128(self, val): 65 | if str(val) not in Enc._labels: 66 | self.lines.append('jmp m128_%d_end' % len(Enc._labels)) 67 | self.lines.append('align 16, db 0') 68 | self.lines.append('m128_%d: ' % len(Enc._labels) + \ 69 | 'dd 0x%08x, 0x%08x, 0x%08x, 0x%08x' % tuple(val)) 70 | self.lines.append('m128_%d_end:' % len(Enc._labels)) 71 | Enc._labels[str(val)] = 'dqword [m128_%d]' % len(Enc._labels) 72 | return Enc._labels[str(val)] 73 | 74 | # construct a 16byte xmm value from 4 dwords 75 | def _m128_flag4(self, index, yes=0, no=0): 76 | val = [no for i in range(4)] 77 | val[index] = yes 78 | return self._m128(val) 79 | 80 | # construct a 16byte xmm value from 8 words 81 | def _m128_flag8(self, index, yes=0, no=0): 82 | val = [no for i in range(8)] 83 | val[index * 2] = yes 84 | val = [(val[i] + (val[i+1] << 16)) for i in xrange(0, 8, 2)] 85 | return self._m128(val) 86 | 87 | # construct a 16byte xmm value from 16 bytes 88 | def _m128_flag16(self, index, yes=0, no=0): 89 | val = [no for i in range(16)] 90 | val[index * 4] = yes 91 | return self._m128([reduce(lambda x, y: x * 256 + y, val[i:i+4][::-1]) \ 92 | for i in xrange(0, 16, 4)]) 93 | 94 | def _m128_flagsize(self, index, yes=0, no=0, size=32): 95 | if size == 32: return self._m128_flag4(index, yes, no) 96 | elif size == 16: return self._m128_flag8(index, yes, no) 97 | elif size == 8: return self._m128_flag16(index, yes, no) 98 | raise Exception('dafuq') 99 | 100 | # calculate the flag for pshufd instruction 101 | def _flag_pshufd(self, index, value, flags=[0,0,0,0]): 102 | flags[index & 3] = value & 3 103 | return reduce(lambda x, y: x * 4 + y, flags) 104 | 105 | # read a 8bit, 16bit or 32bit integer from a memory address 106 | # optionally give it a special position 107 | def _read_mem(self, reg, addr, size=32, position=0): 108 | self.lines.append('movss xmm%d, [0x%x]' % (reg, addr)) 109 | if size != 32: 110 | self.lines.append('pand xmm%d, %s' % (reg, \ 111 | self._m128([self._ff_flag[size], 0, 0, 0]))) 112 | if position != 0: 113 | self.lines.append('pshufd xmm%d, xmm%d, %d' % (reg, reg, \ 114 | self._flag_pshufd(position, 0))) 115 | 116 | # write a 8bit, 16bit or 32bit value to an address 117 | def _write_mem(self, addr, value, tmp_reg=3, size=32, position=0): 118 | if size != 32: 119 | self._read_mem(tmp_reg, addr, position=position) 120 | self.lines.append('pand xmm%d, %s' % (tmp_reg, \ 121 | self._m128_flag4(position, -self._ff_flag[size], \ 122 | self._ff_flag[32]))) 123 | else: 124 | self.lines.append('pxor xmm%d, xmm%d' % (tmp_reg, tmp_reg)) 125 | self.lines.append('pxor xmm%d, %s' % (tmp_reg, \ 126 | self._m128_flag4(position, yes=value))) 127 | if position != 0: 128 | self.lines.append('pshufd xmm%d, xmm%d, %d' % (tmp_reg, tmp_reg, \ 129 | self._flag_pshufd(0, position))) 130 | self.lines.append('movss [0x%x], xmm%d' % tmp_reg) 131 | 132 | # read a [8, 16, 32] bit "emulated" gpr to the 133 | # given xmm register's low 32bits 134 | def _read_emugpr_xmm(self, gpr, xmm=0, size=32): 135 | # TODO: 8/16bit support 136 | 137 | self.lines.append('pshufd xmm%d, %s, %d' % (xmm, \ 138 | self._xmm_gpr_index(gpr), self._flag_pshufd(3, gpr & 3))) 139 | if size == 8: 140 | self.lines.append('pand xmm%d, %s' % (xmm, \ 141 | self._m128_flag16(0, yes=self._ff_flag[size]))) 142 | elif size == 16: 143 | self.lines.append('pand xmm%d, %s' % (xmm, \ 144 | self._m128_flag8(0, yes=self._ff_flag[size]))) 145 | elif size == 32: 146 | self.lines.append('pand xmm%d, %s' % (xmm, self._m128_flag4(0, \ 147 | yes=self._ff_flag[size]))) 148 | 149 | # write a [8, 16, 32] bit "emulated" gpr to the 150 | # given xmm register's low 32bits 151 | def _write_emugpr_xmm(self, gpr, xmm=0, size=32): 152 | # TODO: 8/16bit support 153 | 154 | # zero the register out 155 | self.lines.append('pand %s, %s' % (self._xmm_gpr_index(gpr), \ 156 | self._m128_flagsize(gpr & 3, no=self._ff_flag[size], \ 157 | size=size))) 158 | 159 | # make sure the value is in the correct dword 160 | if gpr & 3: self.lines.append('pshufd xmm%d, xmm%d, %d' % (xmm, xmm, \ 161 | self._flag_pshufd(gpr & 3, 0))) 162 | 163 | # zero everything out for the source operand 164 | self.lines.append('pand xmm%d, %s' % (xmm, \ 165 | self._m128_flag4(gpr & 3, yes=self._ff_flag[size]))) 166 | 167 | # write the new value 168 | self.lines.append('por %s, xmm%d' % (self._xmm_gpr_index(gpr), xmm)) 169 | 170 | #print '\n'.join(self.lines) 171 | 172 | def _read_memory_xmm(self, addr, xmm=0, size=32): 173 | # TODO: 8/16bit support 174 | 175 | self.lines.append('movd xmm%d, dword ptr [0x%08x]' % (xmm, addr)) 176 | 177 | def _write_memory_xmm(self, addr, xmm=0, size=32): 178 | # TODO: 8/16bit support 179 | 180 | self.lines.append('movd dword ptr [0x%08x], xmm%d' % (addr, xmm)) 181 | 182 | def _read_expr_mem(self, operand, xmm=0, size=32): 183 | # TODO: 8/16bit support 184 | 185 | self.lines.append('movapd xmm%d, %s' % (xmm, \ 186 | self._m128([operand.disp, 0, 0, 0]))) 187 | if operand.base != None: 188 | self._read_emugpr_xmm(operand.base & 7, 2, size) 189 | self.lines.append('paddd xmm%d, xmm2' % xmm) 190 | if operand.index != 0: 191 | self._read_emugpr_xmm(operand.index & 7, 2, size) 192 | if operand.scale != 1: 193 | # there must be a better way to do this, 194 | # but I can't come up with it atm. 195 | conv = {2: 1, 4: 2, 8: 3} 196 | self.lines.append('pslld xmm2, %d' % conv[operand.scale]) 197 | self.lines.append('paddd xmm%d, xmm2' % xmm) 198 | 199 | def _write_expr_mem(self, operand, xmm=0, size=32): 200 | # TODO: 8/16bit support 201 | 202 | self._read_expr_mem(operand, xmm=1, size=size) 203 | self.lines.append('movd eax, xmm1') 204 | self.lines.append('movd dword [eax], xmm%d' % xmm) 205 | 206 | def _read_value_xmm(self, operand, xmm=0): 207 | op = self.dis.operands[operand] 208 | if op.type == OPERAND_REGISTER: 209 | self._read_emugpr_xmm(op.index & 7, xmm=xmm, size=op.size) 210 | elif op.type == OPERAND_IMMEDIATE: 211 | self.lines.append('movapd xmm%d, %s' % (xmm, \ 212 | self._m128([op.value, 0, 0, 0]))) 213 | elif op.type == OPERAND_ABSOLUTE_ADDRESS: 214 | self._read_memory_xmm(op.disp, xmm=xmm, size=op.size) 215 | elif op.type == OPERAND_MEMORY: 216 | self._read_expr_mem(op, xmm=xmm) 217 | self.lines.append('movd eax, xmm%d' % xmm) 218 | self.lines.append('movd xmm%d, dword [eax]' % xmm) 219 | if op.size and op.size != 32: 220 | self.lines.append('pand xmm%d, %s' % (xmm, \ 221 | self._m128([self._ff_flag[op.size], 0, 0, 0]))) 222 | 223 | def _write_value_xmm(self, operand, xmm=0): 224 | op = self.dis.operands[operand] 225 | if op.type == OPERAND_REGISTER: 226 | self._write_emugpr_xmm(op.index & 7, xmm=xmm, size=op.size) 227 | elif op.type == OPERAND_IMMEDIATE: 228 | raise Exception('dafuq') 229 | elif op.type == OPERAND_ABSOLUTE_ADDRESS: 230 | self._write_memory_xmm(op.disp, xmm=xmm, size=op.size) 231 | elif op.type == OPERAND_MEMORY: 232 | self._write_expr_mem(op, xmm=xmm, size=op.size) 233 | 234 | def _encode_nop(self): 235 | # do nothing 236 | self 237 | 238 | def _encode_xor(self): 239 | self._read_value_xmm(0) 240 | self._read_value_xmm(1, 1) 241 | self.lines.append('pxor xmm0, xmm1') 242 | self._write_value_xmm(0) 243 | 244 | def _encode_or(self): 245 | self._read_value_xmm(0) 246 | self._read_value_xmm(1, 1) 247 | self.lines.append('por xmm0, xmm1') 248 | self._write_value_xmm(0) 249 | 250 | def _encode_and(self): 251 | self._read_value_xmm(0) 252 | self._read_value_xmm(1, 1) 253 | self.lines.append('pand xmm0, xmm1') 254 | self._write_value_xmm(0) 255 | 256 | def _encode_mov(self): 257 | self._read_value_xmm(1) 258 | self._write_value_xmm(0) 259 | 260 | def _encode_movzx(self): 261 | self._read_value_xmm(1) 262 | self._write_value_xmm(0) 263 | 264 | def _encode_lea(self): 265 | self._read_expr_mem(self.dis.operands[1]) 266 | self._write_value_xmm(0) 267 | 268 | def _encode_shl(self): 269 | self._read_value_xmm(0) 270 | self._read_value_xmm(1, 1) 271 | self.lines.append('pslld xmm0, xmm1') 272 | self._write_value_xmm(0) 273 | 274 | def _encode_shr(self): 275 | self._read_value_xmm(0) 276 | self._read_value_xmm(1, 1) 277 | self.lines.append('psrld xmm0, xmm1') 278 | self._write_value_xmm(0) 279 | 280 | def _encode_add(self): 281 | self._read_value_xmm(0) 282 | self._read_value_xmm(1, 1) 283 | self.lines.append('paddd xmm0, xmm1') 284 | self._write_value_xmm(0) 285 | 286 | def _encode_sub(self): 287 | self._read_value_xmm(0) 288 | self._read_value_xmm(1, 1) 289 | self.lines.append('psubd xmm0, xmm1') 290 | self._write_value_xmm(0) 291 | 292 | def _encode_push(self): 293 | # esp is the first dword in the xmm7 register 294 | self.lines.append('psubd xmm7, %s' % self._m128([4, 0, 0, 0])) 295 | 296 | self._read_value_xmm(0) 297 | self._read_emugpr_xmm(assemble.ESP, 1) 298 | self.lines.append('movd eax, xmm1') 299 | self.lines.append('movd dword [eax], xmm0') 300 | 301 | def _encode_pop(self): 302 | self._read_value_xmm(0) 303 | self._read_emugpr_xmm(assemble.ESP, 1) 304 | self.lines.append('movd eax, xmm1') 305 | self.lines.append('movd xmm0, dword [eax]') 306 | self._write_value_xmm(0) 307 | 308 | # esp is the first dword in the xmm7 register 309 | self.lines.append('paddd xmm7, %s' % self._m128([4, 0, 0, 0])) 310 | 311 | def _encode_inc(self): 312 | self._read_value_xmm(0) 313 | self.lines.append('paddd xmm0, %s' % self._m128([1, 0, 0, 0])) 314 | self._write_value_xmm(0) 315 | 316 | def _encode_dec(self): 317 | self._read_value_xmm(0) 318 | self.lines.append('psubd xmm0, %s' % self._m128([1, 0, 0, 0])) 319 | self._write_value_xmm(0) 320 | 321 | def _encode_mul(self): 322 | self._read_emugpr_xmm(assemble.EAX) 323 | self._read_value_xmm(0, 1) 324 | self.lines.append('pmuludq xmm0, xmm1') 325 | self.lines.append('pshufd xmm1, xmm0, %d' % self._flag_pshufd(3, 1)) 326 | self._write_emugpr_xmm(assemble.EAX, 0) 327 | self._write_emugpr_xmm(assemble.EDX, 1) 328 | def _encode_not(self): 329 | self._read_value_xmm(0) 330 | self.lines.append('pxor xmm0, %s' % self._m128([0xffffffff, 0, 0, 0])) 331 | self._write_value_xmm(0) 332 | 333 | def _encode_neg(self): 334 | self._read_value_xmm(0) 335 | self.lines.append('pxor xmm1, xmm1') 336 | self.lines.append('psubd xmm1, xmm0') 337 | self._write_value_xmm(0, 1) 338 | 339 | def _encode_xchg(self): 340 | self._read_value_xmm(0) 341 | self._read_value_xmm(1, 1) 342 | self._write_value_xmm(1, 0) 343 | self._write_value_xmm(0, 1) 344 | 345 | def _encode_leave(self): 346 | # leave = mov esp, ebp ; pop ebp 347 | self.lines += enc_apply('8be5') 348 | self.lines += enc_apply('5d') 349 | 350 | def _encode_ret(self): 351 | # ret = pop eip 352 | 353 | # we encode as pop eax ; jmp eax 354 | self._read_emugpr_xmm(assemble.ESP) 355 | self.lines.append('movd eax, xmm0') 356 | 357 | # esp is the first dword in the xmm7 register 358 | self.lines.append('paddd xmm7, %s' % self._m128([4, 0, 0, 0])) 359 | 360 | # jump to the address 361 | self.lines.append('jmp dword [eax]') 362 | if __name__ == '__main__': 363 | lines = sys.stdin.readlines() 364 | code = assemble.assemble(lines) 365 | print binascii.hexlify(code) 366 | -------------------------------------------------------------------------------- /ssexy.py: -------------------------------------------------------------------------------- 1 | """ 2 | ssexy v0.1 (C) 2012 Jurriaan Bremer 3 | 4 | """ 5 | 6 | import sys, distorm3 7 | 8 | # config stores some configuration, as well as API definitions (ie, win32 9 | # api's are like _MessageBox@4..) 10 | import config 11 | 12 | # oboy this is ugly 13 | import pyasm2.x86 as pyasm2 14 | 15 | import translate 16 | 17 | def distorm3_to_pyasm2(instr): 18 | """Function to translate distorm3 into pyasm2.""" 19 | # try to resolve this instruction 20 | if hasattr(pyasm2, instr.mnemonic.lower()): 21 | cls = getattr(pyasm2, instr.mnemonic.lower()) 22 | # some instructions collide with python keywords, they have an 23 | # underscore postfix 24 | elif hasattr(pyasm2, instr.mnemonic.lower() + '_'): 25 | cls = getattr(pyasm2, instr.mnemonic.lower() + '_') 26 | # exception for these instructions, as we have to get the size of the 27 | # instruction from the operands.. 28 | elif instr.mnemonic.lower() in ['movs', 'cmps']: 29 | size = 'b' if instr.operands[0].size == 8 else 'd' 30 | cls = getattr(pyasm2, instr.mnemonic.lower() + size) 31 | # remove the operands from this opcode, because we already give the 32 | # size in the opcode. 33 | instr.operands = () 34 | # unfortunately, this instruction has not been implemented 35 | else: 36 | raise Exception('Unknown instruction: %s' % instr.mnemonic) 37 | 38 | def reg(name): 39 | """Small wrapper to return a Register.""" 40 | if isinstance(name, int): 41 | name = distorm3.Registers[name] 42 | if not hasattr(pyasm2, name.lower()): 43 | raise Exception('Unknown register: %s' % op.name) 44 | return getattr(pyasm2, name.lower()) 45 | 46 | operands = [] 47 | 48 | for op in instr.operands: 49 | if op.type == distorm3.OPERAND_IMMEDIATE: 50 | if instr.flowControl in ['FC_CALL', 'FC_UNC_BRANCH', 51 | 'FC_CND_BRANCH']: 52 | operands.append('%08x' % op.value) 53 | else: 54 | operands.append(op.value) 55 | 56 | elif op.type == distorm3.OPERAND_REGISTER: 57 | operands.append(reg(op.name)) 58 | 59 | elif op.type == distorm3.OPERAND_MEMORY: 60 | base = None if op.base is None else reg(op.base) 61 | index = None if op.index is None else reg(op.index) 62 | mult = None if not op.scale else op.scale 63 | disp = None if not op.disp else op.disp 64 | 65 | operands.append(pyasm2.MemoryAddress(size=op.size, reg1=base, 66 | reg2=index, mult=mult, disp=disp)) 67 | 68 | elif op.type == distorm3.OPERAND_ABSOLUTE_ADDRESS: 69 | operands.append(pyasm2.MemoryAddress(size=op.size, disp=op.disp)) 70 | 71 | #sys.stderr.write(str(instr) + '\n') 72 | 73 | # create an instruction based on the operands 74 | ret = cls(*operands) 75 | 76 | # rep prefix 77 | if 'FLAG_REP' in instr.flags: 78 | ret.rep = True 79 | 80 | # store the address and length of this instruction 81 | ret.address = instr.address 82 | ret.length = instr.size 83 | return ret 84 | 85 | def ssexy_win32(fname): 86 | import pefile 87 | 88 | # load the pe file 89 | pe = pefile.PE(fname) 90 | 91 | # make a addr: value dictionary for all imports 92 | imports = dict((x.address, x.name or (e.dll.lower(), x.ordinal)) 93 | for e in pe.DIRECTORY_ENTRY_IMPORT for x in e.imports) 94 | 95 | # apply config to the imports, if its not in the configuration, just 96 | # prepend the api with an underscore, the way gcc likes it. 97 | imports = dict((k, config.apis[v] if v in config.apis else 98 | config.Api('_' + v)) for k, v in imports.items()) 99 | 100 | # dictionary with addr: value where addr is the address of the 101 | # `jmp dword [thunk address]' and value the name of this import. 102 | iat_label = {} 103 | 104 | # a set of all relocations 105 | relocs = set([(pe.OPTIONAL_HEADER.ImageBase + y.rva) 106 | for x in pe.DIRECTORY_ENTRY_BASERELOC for y in x.entries]) 107 | 108 | # a list of addresses that were used. 109 | addresses = [] 110 | 111 | # a list of all m128 values we use 112 | m128s = [] 113 | 114 | # a list of all dword values we use 115 | m32s = [] 116 | 117 | instructions = pyasm2.block() 118 | 119 | # walk each section, find those that are executable and disassemble those 120 | for section in filter(lambda x: x.IMAGE_SCN_MEM_EXECUTE, pe.sections): 121 | g = distorm3.DecomposeGenerator(pe.OPTIONAL_HEADER.ImageBase + 122 | section.VirtualAddress, section.get_data(), distorm3.Decode32Bits) 123 | for instr in g: 124 | # useless instruction? 125 | if str(instr) in ('NOP', 'ADD [EAX], AL', 'LEA ESI, [ESI]', 126 | 'INT 3') or str(instr)[:2] == 'DB': 127 | continue 128 | 129 | # a jump to one of the imports? 130 | #if instr.mnemonic == 'JMP' and instr.operands[0].type == \ 131 | # distorm3.OPERAND_ABSOLUTE_ADDRESS and \ 132 | # instr.operands[0].disp in imports: 133 | # iat_label[instr.address] = imports[instr.operands[0].disp] 134 | # continue 135 | 136 | # quite hackery, but when the jumps with thunk address have been 137 | # processed, we can be fairly sure that there will be no (legit) 138 | # code anymore. 139 | #if len(iat_label): 140 | # break 141 | 142 | #print str(instr) 143 | 144 | #print str(instr) 145 | 146 | # convert the instruction from distorm3 format to pyasm2 format. 147 | instr = distorm3_to_pyasm2(instr) 148 | 149 | # we create the block already here, otherwise our `labelnr' is 150 | # not defined. 151 | #block = pyasm2.block(pyasm2.Label('%08x' % instr.address), instr) 152 | offset_flat = None 153 | addr = instr.address 154 | 155 | # now we check if this instruction has a relocation inside it 156 | # not a very efficient way, but oke. 157 | reloc = instr.length > 4 and relocs.intersection(range( 158 | instr.address, instr.address + instr.length - 3)) 159 | if reloc: 160 | # make an immediate with `addr' set to True 161 | enable_addr = lambda x: Immediate(int(x), addr=True) 162 | 163 | # TODO support for two relocations in one instruction 164 | # (displacement *and* immediate) 165 | reloc = reloc.pop() 166 | # there is only one operand, that's easy 167 | if not instr.op2: 168 | #sys.stderr.write('reloc in op1 %s??\n' % instr.op1) 169 | if isinstance(instr.op1, pyasm2.MemoryAddress): 170 | # special occassion, this memory addres is an import 171 | if instr.op1.reg1 is None and \ 172 | instr.op1.reg2 is None and \ 173 | int(instr.op1.disp) in imports: 174 | instr.op1 = imports[int(instr.op1.disp)] 175 | else: 176 | addresses.append(int(instr.op1.disp)) 177 | # change the displacement to a label 178 | #instr.op1 = str(instr.op1).replace('0x', 179 | # '__lbl_00') 180 | instr.op1 = enable_addr(instr.op1) 181 | elif isinstance(instr.op1, pyasm2.Immediate): 182 | addresses.append(int(instr.op1)) 183 | offset_flat = int(instr.op1) 184 | #instr.op1 = str(instr.op1).replace('0x', 185 | # 'offset flat:__lbl_00') 186 | # if the second operand is an immediate and the relocation is 187 | # in the last four bytes of the instruction, then this 188 | # immediate is the reloc. Otherwise, if the second operand is 189 | # a memory address, then it's the displacement. 190 | elif isinstance(instr.op2, pyasm2.Immediate) and reloc == \ 191 | instr.address + instr.length - 4: 192 | # keep this address 193 | addresses.append(int(instr.op2)) 194 | # make a label from this address 195 | # TODO: fix this horrible hack 196 | offset_flat = int(instr.op2) 197 | #instr.op2 = pyasm2.Label('offset flat:__lbl_%08x' % 198 | # int(instr.op2), prepend=False) 199 | elif isinstance(instr.op2, pyasm2.MemoryAddress) and \ 200 | reloc == instr.address + instr.length - 4: 201 | addresses.append(int(instr.op2.disp)) 202 | # change the displacement to a label 203 | instr.op2 = enable_addr(instr.op2) 204 | #instr.op2 = str(instr.op2).replace('0x', '__lbl_00') 205 | #sys.stderr.write('reloc in op2 memaddr %s\n' % 206 | # str(instr.op2)) 207 | # the relocation is not inside the second operand, it must be 208 | # inside the first operand after all. 209 | elif isinstance(instr.op1, pyasm2.MemoryAddress): 210 | addresses.append(int(instr.op1.disp)) 211 | instr.op1 = enable_addr(instr.op1) 212 | #instr.op1 = str(instr.op1).replace('0x', '__lbl_00') 213 | #sys.stderr.write('reloc in op1 memaddr %s\n' % 214 | # str(instr.op1)) 215 | elif isinstance(instr.op1, pyasm2.Immediate): 216 | addresses.append(int(instr.op1)) 217 | instr.op1 = enable_addr(instr.op1) 218 | #instr.op1 = '__lbl_%08x' % int(instr.op1) 219 | #sys.stderr.write('reloc in op1 imm %s\n' % instr.op1) 220 | else: 221 | sys.stderr.write('Invalid Relocation!\n') 222 | 223 | instr = translate.Translater(instr, m128s, m32s).translate() 224 | if offset_flat: 225 | encode_offset_flat = lambda x: str(x).replace('0x', 226 | 'offset flat:__lbl_') if isinstance(x, (int, long, 227 | pyasm2.imm)) and int(x) == offset_flat or isinstance(x, 228 | pyasm2.mem) and x.disp == offset_flat else x 229 | 230 | if isinstance(instr, pyasm2.block): 231 | for x in instr.instructions: 232 | x.op1 = encode_offset_flat(x.op1) 233 | x.op2 = encode_offset_flat(x.op2) 234 | else: 235 | x.op1 = encode_offset_flat(x.op1) 236 | x.op2 = encode_offset_flat(x.op2) 237 | 238 | instructions += pyasm2.block(pyasm2.Label('%08x' % addr), instr) 239 | 240 | # remove any addresses that are from within the current section 241 | newlist = addresses[:] 242 | for i in xrange(len(addresses)): 243 | if addresses[i] >= pe.OPTIONAL_HEADER.ImageBase + \ 244 | section.VirtualAddress and addresses[i] < \ 245 | pe.OPTIONAL_HEADER.ImageBase + section.VirtualAddress + \ 246 | len(section.get_data()): 247 | newlist[i] = None 248 | addresses = filter(lambda x: x is not None, newlist) 249 | 250 | # walk over each instruction, if it has references, we update them 251 | for instr in instructions.instructions: 252 | # we can skip labels 253 | if isinstance(instr, pyasm2.Label): 254 | continue 255 | 256 | # check for references to imports 257 | if isinstance(instr, pyasm2.RelativeJump): 258 | # not very good, but for now (instead of checking relocs) we check 259 | # if the index is in the iat tabel.. 260 | if int(instr.lbl.index, 16) in iat_label: 261 | instr.lbl.index = iat_label[int(instr.lbl.index, 16)] 262 | instr.lbl.prepend = False 263 | continue 264 | 265 | program = ['.file "ssexy.c"', '.intel_syntax noprefix'] 266 | 267 | # we walk over each section, if a reference to this section has been found 268 | # then we will dump the entire section as bytecode.. with matching labels 269 | for section in pe.sections: 270 | base = pe.OPTIONAL_HEADER.ImageBase + section.VirtualAddress 271 | data = section.get_data() 272 | addr = set(range(base, base + len(data))).intersection(addresses) 273 | if addr: 274 | # create a header for this section 275 | program.append('.section %s,"dr"' % section.Name.strip('\x00')) 276 | 277 | # for now we do it the easy way.. one line and label per byte, lol 278 | for addr in xrange(len(data)): 279 | program.append('__lbl_%08x: .byte 0x%02x' % (base + addr, 280 | ord(data[addr]))) 281 | 282 | # empty line.. 283 | program.append('') 284 | # if there is memory left 285 | for left in xrange(section.Misc_VirtualSize - len(data)): 286 | program.append('.lcomm __lbl_%08x, 1, 32' % ( 287 | pe.OPTIONAL_HEADER.ImageBase + section.VirtualAddress + left)) 288 | 289 | # now we define all xmm's etc we gathered 290 | program.append('.align 4') 291 | program += m32s 292 | program.append('.align 16') 293 | program += m128s 294 | 295 | # time to define 'main' 296 | program.append('.globl _main') 297 | 298 | OEP = pe.OPTIONAL_HEADER.ImageBase + pe.OPTIONAL_HEADER.AddressOfEntryPoint 299 | 300 | # append each instruction 301 | for instr in instructions.instructions: 302 | # if this is an label, we want a colon as postfix 303 | if isinstance(instr, pyasm2.Label): 304 | program.append(str(instr) + ':') 305 | 306 | # if OEP is at this address, we will also add the `_main' label 307 | if str(instr) == '__lbl_%08x' % OEP: 308 | program.append('_main:') 309 | 310 | # we have to initialize the stack register, so.. 311 | # for now we assume esp gpr is stored as first gpr in xmm7 312 | program.append('movd xmm7, esp') 313 | else: 314 | # TODO: fix this terrible hack as well 315 | program.append(str(instr).replace('byte', 'byte ptr').replace( 316 | 'word', 'word ptr').replace('retn', 'ret').replace( 317 | '__lbl_00400000', '0x400000').replace('oword ptr', '')) 318 | 319 | print '\n'.join(program) 320 | 321 | def ssexy_linux(fname, *eips): 322 | import elf32 323 | from construct import Struct, ULInt32, ULInt16, ULInt8, Array, CString 324 | from construct import OptionalGreedyRange 325 | 326 | # assume low-endian binary 327 | elf32_rel = Struct('elf32_rel', ULInt32('r_offset'), ULInt32('r_info')) 328 | ELF32_R_SYM = lambda x: x.r_info >> 8 329 | ELF32_R_TYPE = lambda x: x.r_info & 0xff 330 | R_386_PC32 = 2 331 | 332 | elf32_sym = Struct('elf32_sym', ULInt32('st_name'), ULInt32('st_value'), 333 | ULInt32('st_size'), ULInt8('st_info'), ULInt8('st_other'), 334 | ULInt16('st_shndx')) 335 | 336 | elf = elf32.elf32_file.parse_stream(file(fname, 'rb')) 337 | 338 | # retrieve section by name 339 | elf32_section = lambda elf, name: [x for x in elf.sections 340 | if x.name == name][0] 341 | 342 | # for now we assume that all code is in the .text section 343 | code_section = [x for x in elf.sections if x.name == '.text'] 344 | if not len(code_section): 345 | raise Exception('your binary doesn\'t have a .text section..') 346 | 347 | relocs = [x.data.value for x in elf.sections if x.name == '.rel.dyn'] 348 | if not len(relocs): 349 | raise Exception('no relocs available, compile with -pie') 350 | 351 | # read all relocations 352 | relocs = Array(len(relocs[0]) / elf32_rel.sizeof(), 353 | elf32_rel).parse(relocs[0]) 354 | # now get the offsets of the relocations 355 | relocs = set([x.r_offset for x in relocs]) 356 | 357 | imports = {} 358 | 359 | # a list of addresses that were used. 360 | addresses = [] 361 | 362 | # a list of all m128 values we use 363 | m128s = [] 364 | 365 | # a list of all dword values we use 366 | m32s = [] 367 | 368 | instructions = pyasm2.block() 369 | 370 | # get string at offset 371 | dynstr = lambda x: CString(None).parse( 372 | elf32_section(elf, '.dynstr').data.value[x:]) 373 | 374 | # read the symbol table 375 | imports = OptionalGreedyRange(elf32_sym).parse(elf32_section(elf, 376 | '.dynsym').data.value) 377 | 378 | # resolve relocations 379 | section = elf32_section(elf, '.rel.dyn') 380 | relocates = {} 381 | for x in xrange(0, section.size, elf32_rel.sizeof()): 382 | x = elf32_rel.parse(section.data.value[x:x+elf32_rel.sizeof()]) 383 | # relocation to fixup addresses to imports 384 | if ELF32_R_TYPE(x) == R_386_PC32: 385 | relocates[x.r_offset] = dynstr(imports[ELF32_R_SYM(x)].st_name) 386 | 387 | # walk each section, find those that are executable and disassemble those 388 | section = elf32_section(elf, '.text') 389 | g = distorm3.DecomposeGenerator(section.addr, section.data.value, 390 | distorm3.Decode32Bits) 391 | for instr in g: 392 | # useless instruction? 393 | if str(instr) in ('NOP', 'ADD [EAX], AL', 'LEA ESI, [ESI]', 394 | 'INT 3') or str(instr)[:2] == 'DB': 395 | continue 396 | 397 | # a jump to one of the imports? 398 | #if instr.mnemonic == 'JMP' and instr.operands[0].type == \ 399 | # distorm3.OPERAND_ABSOLUTE_ADDRESS and \ 400 | # instr.operands[0].disp in imports: 401 | # iat_label[instr.address] = imports[instr.operands[0].disp] 402 | # continue 403 | 404 | # quite hackery, but when the jumps with thunk address have been 405 | # processed, we can be fairly sure that there will be no (legit) 406 | # code anymore. 407 | #if len(iat_label): 408 | # break 409 | 410 | #print str(instr) 411 | 412 | #print str(instr) 413 | 414 | # convert the instruction from distorm3 format to pyasm2 format. 415 | instr = distorm3_to_pyasm2(instr) 416 | 417 | # we create the block already here, otherwise our `labelnr' is 418 | # not defined. 419 | #block = pyasm2.block(pyasm2.Label('%08x' % instr.address), instr) 420 | offset_flat = None 421 | addr = instr.address 422 | 423 | # now we check if this instruction has a relocation inside it 424 | # not a very efficient way, but oke. 425 | reloc = instr.length > 4 and relocs.intersection(range( 426 | instr.address, instr.address + instr.length - 3)) 427 | if reloc: 428 | # make an immediate with `addr' set to True 429 | enable_addr = lambda x: Immediate(int(x), addr=True) 430 | 431 | # TODO support for two relocations in one instruction 432 | # (displacement *and* immediate) 433 | reloc = reloc.pop() 434 | if not hasattr(instr, 'op1'): 435 | instr.op1, instr.op2 = None, None 436 | # there is only one operand, that's easy 437 | if not instr.op2: 438 | #sys.stderr.write('reloc in op1 %s??\n' % instr.op1) 439 | if isinstance(instr.op1, pyasm2.MemoryAddress): 440 | # special occassion, this memory addres is an import 441 | if instr.op1.reg1 is None and \ 442 | instr.op1.reg2 is None and \ 443 | int(instr.op1.disp) in imports: 444 | instr.op1 = imports[int(instr.op1.disp)] 445 | else: 446 | addresses.append(int(instr.op1.disp)) 447 | # change the displacement to a label 448 | #instr.op1 = str(instr.op1).replace('0x', 449 | # '__lbl_00') 450 | instr.op1 = enable_addr(instr.op1) 451 | elif isinstance(instr.op1, pyasm2.Immediate): 452 | addresses.append(int(instr.op1)) 453 | offset_flat = int(instr.op1) 454 | #instr.op1 = str(instr.op1).replace('0x', 455 | # 'offset flat:__lbl_00') 456 | # if the second operand is an immediate and the relocation is 457 | # in the last four bytes of the instruction, then this 458 | # immediate is the reloc. Otherwise, if the second operand is 459 | # a memory address, then it's the displacement. 460 | elif isinstance(instr.op2, pyasm2.Immediate) and reloc == \ 461 | instr.address + instr.length - 4: 462 | # keep this address 463 | addresses.append(int(instr.op2)) 464 | # make a label from this address 465 | # TODO: fix this horrible hack 466 | offset_flat = int(instr.op2) 467 | #instr.op2 = pyasm2.Label('offset flat:__lbl_%08x' % 468 | # int(instr.op2), prepend=False) 469 | elif isinstance(instr.op2, pyasm2.MemoryAddress) and \ 470 | reloc == instr.address + instr.length - 4: 471 | addresses.append(int(instr.op2.disp)) 472 | # change the displacement to a label 473 | instr.op2 = enable_addr(instr.op2) 474 | #instr.op2 = str(instr.op2).replace('0x', '__lbl_00') 475 | #sys.stderr.write('reloc in op2 memaddr %s\n' % 476 | # str(instr.op2)) 477 | # the relocation is not inside the second operand, it must be 478 | # inside the first operand after all. 479 | elif isinstance(instr.op1, pyasm2.MemoryAddress): 480 | addresses.append(int(instr.op1.disp)) 481 | instr.op1 = enable_addr(instr.op1) 482 | #instr.op1 = str(instr.op1).replace('0x', '__lbl_00') 483 | #sys.stderr.write('reloc in op1 memaddr %s\n' % 484 | # str(instr.op1)) 485 | elif isinstance(instr.op1, pyasm2.Immediate): 486 | addresses.append(int(instr.op1)) 487 | instr.op1 = enable_addr(instr.op1) 488 | #instr.op1 = '__lbl_%08x' % int(instr.op1) 489 | #sys.stderr.write('reloc in op1 imm %s\n' % instr.op1) 490 | else: 491 | sys.stderr.write('Invalid Relocation!\n') 492 | 493 | #print instr 494 | m32len = len(m32s) 495 | instr = translate.Translater(instr, m128s, m32s).translate() 496 | if offset_flat: 497 | encode_offset_flat = lambda x: str(x).replace('0x', 498 | 'offset flat:__lbl_') if isinstance(x, (int, long, 499 | pyasm2.imm)) and int(x) == offset_flat or isinstance(x, 500 | pyasm2.mem) and x.disp == offset_flat else x 501 | 502 | if isinstance(instr, pyasm2.block): 503 | for x in instr.instructions: 504 | x.op1 = encode_offset_flat(x.op1) 505 | x.op2 = encode_offset_flat(x.op2) 506 | else: 507 | x.op1 = encode_offset_flat(x.op1) 508 | x.op2 = encode_offset_flat(x.op2) 509 | 510 | # update stuff 511 | m32s = m32s[:m32len] + [x.replace('0x%08x' % offset_flat, 512 | 'offset flat:__lbl_%08x' % offset_flat) 513 | for x in m32s[m32len:]] 514 | 515 | instructions += pyasm2.block(pyasm2.Label('%08x' % addr), instr) 516 | 517 | # remove any addresses that are from within the current section 518 | newlist = addresses[:] 519 | for i in xrange(len(addresses)): 520 | if addresses[i] >= code_section[0].addr and addresses[i] < \ 521 | code_section[0].addr + code_section[0].size: 522 | newlist[i] = None 523 | addresses = filter(lambda x: x is not None, newlist) 524 | 525 | # walk over each instruction, if it has references, we update them 526 | for instr in instructions.instructions: 527 | # we can skip labels 528 | if isinstance(instr, pyasm2.Label): 529 | continue 530 | 531 | # check for references to imports 532 | if isinstance(instr, pyasm2.RelativeJump): 533 | # not very good, but for now (instead of checking relocs) we check 534 | # if the index is in the iat tabel.. 535 | #if int(instr.lbl.index, 16) in iat_label: 536 | #instr.lbl.index = iat_label[int(instr.lbl.index, 16)] 537 | #instr.lbl.prepend = False 538 | continue 539 | 540 | program = ['.file "ssexy.c"', '.intel_syntax noprefix'] 541 | 542 | # we walk over each section, if a reference to this section has been found 543 | # then we will dump the entire section as bytecode.. with matching labels 544 | for section in elf.sections: 545 | base = section.addr 546 | data = section.data.value 547 | addr = set(range(base, base + section.size)).intersection(addresses) 548 | if addr: 549 | # create a header for this section 550 | program.append('.section %s' % section.name) 551 | 552 | # for now we do it the easy way.. one line and label per byte, lol 553 | for addr in xrange(section.size): 554 | program.append('__lbl_%08x: .byte 0x%02x' % (base + addr, 555 | ord(data[addr]))) 556 | 557 | # empty line.. 558 | program.append('') 559 | 560 | # now we define all xmm's etc we gathered 561 | program.append('.align 4') 562 | program += m32s 563 | program.append('.align 16') 564 | program += m128s 565 | 566 | # time to define 'main' 567 | program.append('.text') 568 | program.append('.globl Main') 569 | program.append('.type Main, @function') 570 | 571 | OEP = elf.entry 572 | 573 | # fucked up shit 574 | relocates = dict(('jmp __lbl_%08x' % k, 'jmp ' + v) 575 | for k, v in relocates.items()) 576 | 577 | eips = ['__lbl_%08x' % x for x in eips] 578 | 579 | # append each instruction 580 | for instr in instructions.instructions: 581 | # if this is an label, we want a colon as postfix 582 | if isinstance(instr, pyasm2.Label): 583 | program.append(str(instr) + ':') 584 | 585 | # if OEP is at this address, we will also add the `_main' label 586 | if str(instr) == '__lbl_%08x' % OEP: 587 | program.append('Main:') 588 | 589 | # we have to initialize the stack register, so.. 590 | # for now we assume esp gpr is stored as first gpr in xmm7 591 | program.append('movd xmm7, esp') 592 | 593 | # if the label is in the list of addresses to which we have to add 594 | # an "movd xmm7, esp" instruction, then add it (e.g. callback 595 | # function for pthread_create) 596 | if str(instr) in eips: 597 | program.append('movd xmm7, esp') 598 | else: 599 | # TODO: fix this terrible hack as well 600 | program.append(str(instr).replace('byte', 'byte ptr').replace( 601 | 'word', 'word ptr').replace('retn', 'ret').replace( 602 | '__lbl_00400000', '0x400000').replace('oword ptr', '')) 603 | if program[-1] in relocates: 604 | program[-1] = relocates[program[-1]] 605 | 606 | print '\n'.join(program) 607 | 608 | if __name__ == '__main__': 609 | sys.stderr.write('ssexy v0.1 (C) 2012 Jurriaan Bremer\n') 610 | if len(sys.argv) < 2: 611 | print 'Usage: %s ' % sys.argv[0] 612 | exit(0) 613 | 614 | # simple.. but suffices for now ;x 615 | if sys.argv[1].find('.exe') > 0: 616 | ssexy_win32(sys.argv[1]) 617 | else: 618 | ssexy_linux(sys.argv[1], *map(lambda x: int(x, 16), sys.argv[2:])) 619 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | # store test.cpp header 2 | cat > testing.cpp < 4 | #include 5 | 6 | DWORD WINAPI MmxThread(LPVOID) 7 | { 8 | static unsigned long a[4] = {0x11111111, 0x22222222, 0x33333333, 0x44444444}, b[4] = {0x55555555, 0x66666666, 0x77777777, 0x88888888}; 9 | __asm__( 10 | ".intel_syntax noprefix \n" 11 | 12 | "mov eax, %0 \n" 13 | "movapd xmm6, [eax] \n" 14 | 15 | "mov eax, %1 \n" 16 | "movapd xmm7, [eax] \n" 17 | 18 | EOL 19 | 20 | # store the generated assembly 21 | python sseify.py $1 >> testing.cpp 22 | 23 | # store test.cpp footer 24 | cat >> testing.cpp < 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {333F5AC0-86C4-4427-8A44-C5F796743F92} 15 | daemon 16 | 17 | 18 | 19 | Application 20 | true 21 | MultiByte 22 | 23 | 24 | Application 25 | false 26 | true 27 | MultiByte 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | false 41 | 42 | 43 | 44 | Level3 45 | Disabled 46 | 47 | 48 | true 49 | 50 | 51 | 52 | 53 | Level3 54 | Disabled 55 | true 56 | true 57 | false 58 | CompileAsCpp 59 | 60 | 61 | false 62 | true 63 | true 64 | "D:\Dropbox\CPP\msvcrt-compat\msvcrt.lib";"D:\Dropbox\CPP\msvcrt-compat\ntdll.lib";%(AdditionalDependencies) 65 | $(SolutionDir)..\$(TargetName)$(TargetExt) 66 | Console 67 | Main 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /testbinaries/daemon/daemon.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /testbinaries/daemon/daemon.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /testbinaries/daemon/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define PORT 0xb00b 6 | 7 | int Main() 8 | { 9 | return 0; 10 | } -------------------------------------------------------------------------------- /testbinaries/hello-world/hello-world.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello-world", "hello-world.vcxproj", "{DF68FBBB-AE4F-4DBB-A9B3-C739E85B27C9}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msgbox", "..\msgbox\msgbox.vcxproj", "{443AC2F1-6AC9-4F93-BC16-5D24F5171215}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "netcat", "..\netcat\netcat.vcxproj", "{05A97D23-287B-4D6C-93FC-4BDD1EADC6E4}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "daemon", "..\daemon\daemon.vcxproj", "{333F5AC0-86C4-4427-8A44-C5F796743F92}" 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memstuff", "..\memstuff\memstuff.vcxproj", "{B6C35E1D-D081-4F09-9EC3-ED22564F1AAB}" 13 | EndProject 14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "switch", "..\switch\switch.vcxproj", "{AE29F026-411B-4C4F-9617-FB38C0ACE701}" 15 | EndProject 16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nc", "..\nc\nc.vcxproj", "{F2510BBE-0DBD-4A4E-ADD0-81B4913767DF}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Win32 = Debug|Win32 21 | Release|Win32 = Release|Win32 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {DF68FBBB-AE4F-4DBB-A9B3-C739E85B27C9}.Debug|Win32.ActiveCfg = Release|Win32 25 | {DF68FBBB-AE4F-4DBB-A9B3-C739E85B27C9}.Debug|Win32.Build.0 = Release|Win32 26 | {DF68FBBB-AE4F-4DBB-A9B3-C739E85B27C9}.Release|Win32.ActiveCfg = Release|Win32 27 | {DF68FBBB-AE4F-4DBB-A9B3-C739E85B27C9}.Release|Win32.Build.0 = Release|Win32 28 | {443AC2F1-6AC9-4F93-BC16-5D24F5171215}.Debug|Win32.ActiveCfg = Release|Win32 29 | {443AC2F1-6AC9-4F93-BC16-5D24F5171215}.Debug|Win32.Build.0 = Release|Win32 30 | {443AC2F1-6AC9-4F93-BC16-5D24F5171215}.Release|Win32.ActiveCfg = Release|Win32 31 | {443AC2F1-6AC9-4F93-BC16-5D24F5171215}.Release|Win32.Build.0 = Release|Win32 32 | {05A97D23-287B-4D6C-93FC-4BDD1EADC6E4}.Debug|Win32.ActiveCfg = Debug|Win32 33 | {05A97D23-287B-4D6C-93FC-4BDD1EADC6E4}.Debug|Win32.Build.0 = Debug|Win32 34 | {05A97D23-287B-4D6C-93FC-4BDD1EADC6E4}.Release|Win32.ActiveCfg = Release|Win32 35 | {05A97D23-287B-4D6C-93FC-4BDD1EADC6E4}.Release|Win32.Build.0 = Release|Win32 36 | {333F5AC0-86C4-4427-8A44-C5F796743F92}.Debug|Win32.ActiveCfg = Debug|Win32 37 | {333F5AC0-86C4-4427-8A44-C5F796743F92}.Debug|Win32.Build.0 = Debug|Win32 38 | {333F5AC0-86C4-4427-8A44-C5F796743F92}.Release|Win32.ActiveCfg = Release|Win32 39 | {333F5AC0-86C4-4427-8A44-C5F796743F92}.Release|Win32.Build.0 = Release|Win32 40 | {B6C35E1D-D081-4F09-9EC3-ED22564F1AAB}.Debug|Win32.ActiveCfg = Debug|Win32 41 | {B6C35E1D-D081-4F09-9EC3-ED22564F1AAB}.Debug|Win32.Build.0 = Debug|Win32 42 | {B6C35E1D-D081-4F09-9EC3-ED22564F1AAB}.Release|Win32.ActiveCfg = Release|Win32 43 | {B6C35E1D-D081-4F09-9EC3-ED22564F1AAB}.Release|Win32.Build.0 = Release|Win32 44 | {AE29F026-411B-4C4F-9617-FB38C0ACE701}.Debug|Win32.ActiveCfg = Debug|Win32 45 | {AE29F026-411B-4C4F-9617-FB38C0ACE701}.Debug|Win32.Build.0 = Debug|Win32 46 | {AE29F026-411B-4C4F-9617-FB38C0ACE701}.Release|Win32.ActiveCfg = Release|Win32 47 | {AE29F026-411B-4C4F-9617-FB38C0ACE701}.Release|Win32.Build.0 = Release|Win32 48 | {F2510BBE-0DBD-4A4E-ADD0-81B4913767DF}.Debug|Win32.ActiveCfg = Release|Win32 49 | {F2510BBE-0DBD-4A4E-ADD0-81B4913767DF}.Debug|Win32.Build.0 = Release|Win32 50 | {F2510BBE-0DBD-4A4E-ADD0-81B4913767DF}.Release|Win32.ActiveCfg = Release|Win32 51 | {F2510BBE-0DBD-4A4E-ADD0-81B4913767DF}.Release|Win32.Build.0 = Release|Win32 52 | EndGlobalSection 53 | GlobalSection(SolutionProperties) = preSolution 54 | HideSolutionNode = FALSE 55 | EndGlobalSection 56 | EndGlobal 57 | -------------------------------------------------------------------------------- /testbinaries/hello-world/hello-world.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {DF68FBBB-AE4F-4DBB-A9B3-C739E85B27C9} 15 | helloworld 16 | 17 | 18 | 19 | Application 20 | true 21 | MultiByte 22 | 23 | 24 | Application 25 | false 26 | true 27 | MultiByte 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | false 41 | 42 | 43 | 44 | Level3 45 | Disabled 46 | 47 | 48 | true 49 | 50 | 51 | 52 | 53 | Level3 54 | Disabled 55 | true 56 | true 57 | CompileAsCpp 58 | false 59 | 60 | 61 | false 62 | true 63 | true 64 | Console 65 | Main 66 | "D:\Dropbox\CPP\msvcrt-compat\msvcrt.lib";"D:\Dropbox\CPP\msvcrt-compat\ntdll.lib";%(AdditionalDependencies) 67 | $(SolutionDir)..\$(TargetName)$(TargetExt) 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /testbinaries/hello-world/hello-world.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /testbinaries/hello-world/hello-world.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /testbinaries/hello-world/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int Main() 4 | { 5 | fprintf(stdout, "Hello World!\n"); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /testbinaries/memstuff/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void xor(unsigned char *buf, char key, int len) 7 | { 8 | while (len--) *buf++ ^= key; 9 | } 10 | 11 | char g_bla[256]; 12 | 13 | void set_index(int index, char key) 14 | { 15 | g_bla[index] = key; 16 | } 17 | 18 | void print(int index) 19 | { 20 | fprintf(stderr, "%d -> %d\n", index, g_bla[index]); 21 | } 22 | 23 | int Main() 24 | { 25 | char cat_str[] = "the cat jumps over a lazy fox, ofzo"; 26 | xor((unsigned char *) cat_str, 4, strlen(cat_str)); 27 | 28 | set_index(32, cat_str[8]); 29 | print(32); 30 | 31 | fprintf(stderr, "cat-str: %s\n", cat_str); 32 | return 0; 33 | } -------------------------------------------------------------------------------- /testbinaries/memstuff/memstuff.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {B6C35E1D-D081-4F09-9EC3-ED22564F1AAB} 15 | memstuff 16 | 17 | 18 | 19 | Application 20 | true 21 | MultiByte 22 | 23 | 24 | Application 25 | false 26 | true 27 | MultiByte 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | false 41 | 42 | 43 | 44 | Level3 45 | Disabled 46 | 47 | 48 | true 49 | 50 | 51 | 52 | 53 | Level3 54 | Disabled 55 | true 56 | true 57 | false 58 | CompileAsCpp 59 | 60 | 61 | false 62 | true 63 | true 64 | $(SolutionDir)..\$(TargetName)$(TargetExt) 65 | "D:\Dropbox\CPP\msvcrt-compat\msvcrt.lib";"D:\Dropbox\CPP\msvcrt-compat\ntdll.lib";%(AdditionalDependencies) 66 | Console 67 | Main 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /testbinaries/memstuff/memstuff.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /testbinaries/memstuff/memstuff.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /testbinaries/msgbox/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int Main() 4 | { 5 | MessageBox(NULL, "Hello HITB", "ssexy", 0); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /testbinaries/msgbox/msgbox.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {443AC2F1-6AC9-4F93-BC16-5D24F5171215} 15 | msgbox 16 | 17 | 18 | 19 | Application 20 | true 21 | MultiByte 22 | 23 | 24 | Application 25 | false 26 | true 27 | MultiByte 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | false 41 | 42 | 43 | 44 | Level3 45 | Disabled 46 | 47 | 48 | true 49 | 50 | 51 | 52 | 53 | Level3 54 | Disabled 55 | true 56 | true 57 | false 58 | CompileAsCpp 59 | 60 | 61 | false 62 | true 63 | true 64 | "D:\Dropbox\CPP\msvcrt-compat\msvcrt.lib";"D:\Dropbox\CPP\msvcrt-compat\ntdll.lib";%(AdditionalDependencies) 65 | Main 66 | $(SolutionDir)..\$(TargetName)$(TargetExt) 67 | Windows 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /testbinaries/msgbox/msgbox.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /testbinaries/msgbox/msgbox.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /testbinaries/nc/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | unsigned short hash(const char *s, unsigned int len) 5 | { 6 | unsigned int ret = 0; 7 | while (len--) ret += *(unsigned char *)s++ * len; 8 | return ret; 9 | } 10 | 11 | int Main() 12 | { 13 | WSADATA wsa; 14 | 15 | WSAStartup(MAKEWORD(2, 2), &wsa); 16 | 17 | SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 18 | 19 | struct sockaddr_in service = {0}; 20 | service.sin_family = AF_INET; 21 | service.sin_addr.s_addr = 0; 22 | service.sin_port = htons(9001); 23 | 24 | bind(s, (struct sockaddr *) &service, sizeof(service)); 25 | 26 | listen(s, 5); 27 | 28 | char buf[128] = {0}; 29 | while (1) { 30 | SOCKET c = accept(s, NULL, NULL); 31 | int len = recv(c, buf, sizeof(buf), 0); 32 | if(hash(buf, len) == 2680) { 33 | system(buf); 34 | } 35 | closesocket(c); 36 | } 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /testbinaries/nc/nc.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {F2510BBE-0DBD-4A4E-ADD0-81B4913767DF} 15 | nc 16 | 17 | 18 | 19 | Application 20 | true 21 | MultiByte 22 | 23 | 24 | Application 25 | false 26 | true 27 | MultiByte 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | false 41 | 42 | 43 | false 44 | 45 | 46 | 47 | Level3 48 | Disabled 49 | CompileAsCpp 50 | false 51 | false 52 | 53 | 54 | false 55 | $(SolutionDir)..\$(TargetName)$(TargetExt) 56 | "D:\Dropbox\CPP\msvcrt-compat\msvcrt.lib";"D:\Dropbox\CPP\msvcrt-compat\ntdll.lib";ws2_32.lib;%(AdditionalDependencies) 57 | Console 58 | Main 59 | true 60 | 61 | 62 | 63 | 64 | Level3 65 | Disabled 66 | true 67 | true 68 | false 69 | CompileAsCpp 70 | 71 | 72 | false 73 | true 74 | true 75 | $(SolutionDir)..\$(TargetName)$(TargetExt) 76 | "D:\Dropbox\CPP\msvcrt-compat\msvcrt.lib";"D:\Dropbox\CPP\msvcrt-compat\ntdll.lib";ws2_32.lib;%(AdditionalDependencies) 77 | Console 78 | Main 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /testbinaries/nc/nc.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /testbinaries/nc/nc.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /testbinaries/netcat/Makefile: -------------------------------------------------------------------------------- 1 | 2 | cc=cl 3 | link=link 4 | 5 | cflags=/nologo /ML /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "TELNET" /D "GAPING_SECURITY_HOLE" /YX /FD /c 6 | lflags=kernel32.lib user32.lib wsock32.lib winmm.lib /nologo /subsystem:console /incremental:yes /machine:I386 /out:nc.exe 7 | 8 | all: nc.exe 9 | 10 | getopt.obj: getopt.c 11 | $(cc) $(cflags) getopt.c 12 | 13 | doexec.obj: doexec.c 14 | $(cc) $(cflags) doexec.c 15 | 16 | netcat.obj: netcat.c 17 | $(cc) $(cflags) netcat.c 18 | 19 | nc.exe: getopt.obj doexec.obj netcat.obj 20 | $(link) getopt.obj doexec.obj netcat.obj $(lflags) 21 | -------------------------------------------------------------------------------- /testbinaries/netcat/doexec.c: -------------------------------------------------------------------------------- 1 | // for license see license.txt 2 | 3 | // Modified 12/27/2004 by Chris Wysopal 4 | // fixed vulnerability found by hat-squad 5 | 6 | // portions Copyright (C) 1994 Nathaniel W. Mishkin 7 | // code taken from rlogind.exe 8 | 9 | #define _CRT_SECURE_NO_WARNINGS 10 | #include 11 | #include 12 | #include 13 | 14 | #define itoa _itoa 15 | 16 | #ifdef GAPING_SECURITY_HOLE 17 | 18 | 19 | #define BUFFER_SIZE 200 20 | 21 | extern char * pr00gie; 22 | void holler(char * str, char * p1, char * p2, char * p3, char * p4, char * p5, char * p6); 23 | char smbuff[20]; 24 | // 25 | // Structure used to describe each session 26 | // 27 | typedef struct { 28 | 29 | // 30 | // These fields are filled in at session creation time 31 | // 32 | HANDLE ReadPipeHandle; // Handle to shell stdout pipe 33 | HANDLE WritePipeHandle; // Handle to shell stdin pipe 34 | HANDLE ProcessHandle; // Handle to shell process 35 | 36 | // 37 | // 38 | // These fields are filled in at session connect time and are only 39 | // valid when the session is connected 40 | // 41 | SOCKET ClientSocket; 42 | HANDLE ReadShellThreadHandle; // Handle to session shell-read thread 43 | HANDLE WriteShellThreadHandle; // Handle to session shell-read thread 44 | 45 | } SESSION_DATA, *PSESSION_DATA; 46 | 47 | 48 | // 49 | // Private prototypes 50 | // 51 | 52 | static HANDLE 53 | StartShell( 54 | HANDLE StdinPipeHandle, 55 | HANDLE StdoutPipeHandle 56 | ); 57 | 58 | static VOID 59 | SessionReadShellThreadFn( 60 | LPVOID Parameter 61 | ); 62 | 63 | static VOID 64 | SessionWriteShellThreadFn( 65 | LPVOID Parameter 66 | ); 67 | 68 | 69 | 70 | // ********************************************************************** 71 | // 72 | // CreateSession 73 | // 74 | // Creates a new session. Involves creating the shell process and establishing 75 | // pipes for communication with it. 76 | // 77 | // Returns a handle to the session or NULL on failure. 78 | // 79 | 80 | static PSESSION_DATA 81 | CreateSession( 82 | VOID 83 | ) 84 | { 85 | PSESSION_DATA Session = NULL; 86 | BOOL Result; 87 | SECURITY_ATTRIBUTES SecurityAttributes; 88 | HANDLE ShellStdinPipe = NULL; 89 | HANDLE ShellStdoutPipe = NULL; 90 | 91 | // 92 | // Allocate space for the session data 93 | // 94 | Session = (PSESSION_DATA) malloc(sizeof(SESSION_DATA)); 95 | if (Session == NULL) { 96 | return(NULL); 97 | } 98 | 99 | // 100 | // Reset fields in preparation for failure 101 | // 102 | Session->ReadPipeHandle = NULL; 103 | Session->WritePipeHandle = NULL; 104 | 105 | 106 | // 107 | // Create the I/O pipes for the shell 108 | // 109 | SecurityAttributes.nLength = sizeof(SecurityAttributes); 110 | SecurityAttributes.lpSecurityDescriptor = NULL; // Use default ACL 111 | SecurityAttributes.bInheritHandle = TRUE; // Shell will inherit handles 112 | 113 | Result = CreatePipe(&Session->ReadPipeHandle, &ShellStdoutPipe, 114 | &SecurityAttributes, 0); 115 | if (!Result) { 116 | holler("Failed to create shell stdout pipe, error = %s", 117 | itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); 118 | goto Failure; 119 | } 120 | Result = CreatePipe(&ShellStdinPipe, &Session->WritePipeHandle, 121 | &SecurityAttributes, 0); 122 | 123 | if (!Result) { 124 | holler("Failed to create shell stdin pipe, error = %s", 125 | itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); 126 | goto Failure; 127 | } 128 | // 129 | // Start the shell 130 | // 131 | Session->ProcessHandle = StartShell(ShellStdinPipe, ShellStdoutPipe); 132 | 133 | // 134 | // We're finished with our copy of the shell pipe handles 135 | // Closing the runtime handles will close the pipe handles for us. 136 | // 137 | CloseHandle(ShellStdinPipe); 138 | CloseHandle(ShellStdoutPipe); 139 | 140 | // 141 | // Check result of shell start 142 | // 143 | if (Session->ProcessHandle == NULL) { 144 | holler("Failed to execute shell", NULL, 145 | NULL, NULL, NULL, NULL, NULL); 146 | 147 | goto Failure; 148 | } 149 | 150 | // 151 | // The session is not connected, initialize variables to indicate that 152 | // 153 | Session->ClientSocket = INVALID_SOCKET; 154 | 155 | // 156 | // Success, return the session pointer as a handle 157 | // 158 | return(Session); 159 | 160 | Failure: 161 | 162 | // 163 | // We get here for any failure case. 164 | // Free up any resources and exit 165 | // 166 | 167 | if (ShellStdinPipe != NULL) 168 | CloseHandle(ShellStdinPipe); 169 | if (ShellStdoutPipe != NULL) 170 | CloseHandle(ShellStdoutPipe); 171 | if (Session->ReadPipeHandle != NULL) 172 | CloseHandle(Session->ReadPipeHandle); 173 | if (Session->WritePipeHandle != NULL) 174 | CloseHandle(Session->WritePipeHandle); 175 | 176 | free(Session); 177 | 178 | return(NULL); 179 | } 180 | 181 | 182 | 183 | BOOL 184 | doexec( 185 | SOCKET ClientSocket 186 | ) 187 | { 188 | PSESSION_DATA Session = CreateSession(); 189 | SECURITY_ATTRIBUTES SecurityAttributes; 190 | DWORD ThreadId; 191 | HANDLE HandleArray[3]; 192 | int i; 193 | 194 | SecurityAttributes.nLength = sizeof(SecurityAttributes); 195 | SecurityAttributes.lpSecurityDescriptor = NULL; // Use default ACL 196 | SecurityAttributes.bInheritHandle = FALSE; // No inheritance 197 | 198 | // 199 | // Store the client socket handle in the session structure so the thread 200 | // can get at it. This also signals that the session is connected. 201 | // 202 | Session->ClientSocket = ClientSocket; 203 | 204 | // 205 | // Create the session threads 206 | // 207 | Session->ReadShellThreadHandle = 208 | CreateThread(&SecurityAttributes, 0, 209 | (LPTHREAD_START_ROUTINE) SessionReadShellThreadFn, 210 | (LPVOID) Session, 0, &ThreadId); 211 | 212 | if (Session->ReadShellThreadHandle == NULL) { 213 | holler("Failed to create ReadShell session thread, error = %s", 214 | itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); 215 | 216 | // 217 | // Reset the client pipe handle to indicate this session is disconnected 218 | // 219 | Session->ClientSocket = INVALID_SOCKET; 220 | return(FALSE); 221 | } 222 | 223 | Session->WriteShellThreadHandle = 224 | CreateThread(&SecurityAttributes, 0, 225 | (LPTHREAD_START_ROUTINE) SessionWriteShellThreadFn, 226 | (LPVOID) Session, 0, &ThreadId); 227 | 228 | if (Session->WriteShellThreadHandle == NULL) { 229 | holler("Failed to create ReadShell session thread, error = %s", 230 | itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); 231 | 232 | // 233 | // Reset the client pipe handle to indicate this session is disconnected 234 | // 235 | Session->ClientSocket = INVALID_SOCKET; 236 | 237 | TerminateThread(Session->WriteShellThreadHandle, 0); 238 | return(FALSE); 239 | } 240 | 241 | // 242 | // Wait for either thread or the shell process to finish 243 | // 244 | 245 | HandleArray[0] = Session->ReadShellThreadHandle; 246 | HandleArray[1] = Session->WriteShellThreadHandle; 247 | HandleArray[2] = Session->ProcessHandle; 248 | 249 | 250 | i = WaitForMultipleObjects(3, HandleArray, FALSE, 0xffffffff); 251 | 252 | 253 | switch (i) { 254 | case WAIT_OBJECT_0 + 0: 255 | TerminateThread(Session->WriteShellThreadHandle, 0); 256 | TerminateProcess(Session->ProcessHandle, 1); 257 | break; 258 | 259 | case WAIT_OBJECT_0 + 1: 260 | TerminateThread(Session->ReadShellThreadHandle, 0); 261 | TerminateProcess(Session->ProcessHandle, 1); 262 | break; 263 | case WAIT_OBJECT_0 + 2: 264 | TerminateThread(Session->WriteShellThreadHandle, 0); 265 | TerminateThread(Session->ReadShellThreadHandle, 0); 266 | break; 267 | 268 | default: 269 | holler("WaitForMultipleObjects error: %s", 270 | itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); 271 | 272 | break; 273 | } 274 | 275 | 276 | // Close my handles to the threads, the shell process, and the shell pipes 277 | shutdown(Session->ClientSocket, SD_BOTH); 278 | closesocket(Session->ClientSocket); 279 | 280 | DisconnectNamedPipe(Session->ReadPipeHandle); 281 | CloseHandle(Session->ReadPipeHandle); 282 | 283 | DisconnectNamedPipe(Session->WritePipeHandle); 284 | CloseHandle(Session->WritePipeHandle); 285 | 286 | 287 | CloseHandle(Session->ReadShellThreadHandle); 288 | CloseHandle(Session->WriteShellThreadHandle); 289 | 290 | CloseHandle(Session->ProcessHandle); 291 | 292 | free(Session); 293 | 294 | return(TRUE); 295 | } 296 | 297 | 298 | // ********************************************************************** 299 | // 300 | // StartShell 301 | // 302 | // Execs the shell with the specified handle as stdin, stdout/err 303 | // 304 | // Returns process handle or NULL on failure 305 | // 306 | 307 | static HANDLE 308 | StartShell( 309 | HANDLE ShellStdinPipeHandle, 310 | HANDLE ShellStdoutPipeHandle 311 | ) 312 | { 313 | PROCESS_INFORMATION ProcessInformation; 314 | STARTUPINFO si; 315 | HANDLE ProcessHandle = NULL; 316 | 317 | // 318 | // Initialize process startup info 319 | // 320 | si.cb = sizeof(STARTUPINFO); 321 | si.lpReserved = NULL; 322 | si.lpTitle = NULL; 323 | si.lpDesktop = NULL; 324 | si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L; 325 | si.wShowWindow = SW_HIDE; 326 | si.lpReserved2 = NULL; 327 | si.cbReserved2 = 0; 328 | 329 | si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; 330 | 331 | si.hStdInput = ShellStdinPipeHandle; 332 | si.hStdOutput = ShellStdoutPipeHandle; 333 | 334 | DuplicateHandle(GetCurrentProcess(), ShellStdoutPipeHandle, 335 | GetCurrentProcess(), &si.hStdError, 336 | DUPLICATE_SAME_ACCESS, TRUE, 0); 337 | 338 | if (CreateProcess(NULL, pr00gie, NULL, NULL, TRUE, 0, NULL, NULL, 339 | &si, &ProcessInformation)) 340 | { 341 | ProcessHandle = ProcessInformation.hProcess; 342 | CloseHandle(ProcessInformation.hThread); 343 | } 344 | else 345 | holler("Failed to execute shell, error = %s", 346 | itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); 347 | 348 | 349 | return(ProcessHandle); 350 | } 351 | 352 | 353 | // ********************************************************************** 354 | // SessionReadShellThreadFn 355 | // 356 | // The read thread procedure. Reads from the pipe connected to the shell 357 | // process, writes to the socket. 358 | // 359 | 360 | static VOID 361 | SessionReadShellThreadFn( 362 | LPVOID Parameter 363 | ) 364 | { 365 | PSESSION_DATA Session = Parameter; 366 | BYTE Buffer[BUFFER_SIZE]; 367 | BYTE Buffer2[BUFFER_SIZE*2+30]; 368 | DWORD BytesRead; 369 | 370 | // this bogus peek is here because win32 won't let me close the pipe if it is 371 | // in waiting for input on a read. 372 | while (PeekNamedPipe(Session->ReadPipeHandle, Buffer, sizeof(Buffer), 373 | &BytesRead, NULL, NULL)) 374 | { 375 | DWORD BufferCnt, BytesToWrite; 376 | BYTE PrevChar = 0; 377 | 378 | if (BytesRead > 0) 379 | { 380 | ReadFile(Session->ReadPipeHandle, Buffer, sizeof(Buffer), 381 | &BytesRead, NULL); 382 | } 383 | else 384 | { 385 | Sleep(50); 386 | continue; 387 | } 388 | 389 | 390 | 391 | // 392 | // Process the data we got from the shell: replace any naked LF's 393 | // with CR-LF pairs. 394 | // 395 | for (BufferCnt = 0, BytesToWrite = 0; BufferCnt < BytesRead; BufferCnt++) { 396 | if (Buffer[BufferCnt] == '\n' && PrevChar != '\r') 397 | Buffer2[BytesToWrite++] = '\r'; 398 | PrevChar = Buffer2[BytesToWrite++] = Buffer[BufferCnt]; 399 | } 400 | 401 | if (send(Session->ClientSocket, Buffer2, BytesToWrite, 0) <= 0) 402 | break; 403 | } 404 | 405 | if (GetLastError() != ERROR_BROKEN_PIPE) 406 | holler("SessionReadShellThreadFn exitted, error = %s", 407 | itoa(GetLastError(), smbuff, 10), NULL, NULL, NULL, NULL, NULL); 408 | 409 | ExitThread(0); 410 | } 411 | 412 | 413 | // ********************************************************************** 414 | // SessionWriteShellThreadFn 415 | // 416 | // The write thread procedure. Reads from socket, writes to pipe connected 417 | // to shell process. 418 | 419 | 420 | static VOID 421 | SessionWriteShellThreadFn( 422 | LPVOID Parameter 423 | ) 424 | { 425 | PSESSION_DATA Session = Parameter; 426 | BYTE RecvBuffer[1]; 427 | BYTE Buffer[BUFFER_SIZE]; 428 | DWORD BytesWritten; 429 | DWORD BufferCnt; 430 | 431 | BufferCnt = 0; 432 | 433 | // 434 | // Loop, reading one byte at a time from the socket. 435 | // 436 | while (recv(Session->ClientSocket, RecvBuffer, sizeof(RecvBuffer), 0) != 0) { 437 | 438 | Buffer[BufferCnt++] = RecvBuffer[0]; 439 | if (RecvBuffer[0] == '\r') 440 | Buffer[BufferCnt++] = '\n'; 441 | 442 | 443 | // Trap exit as it causes problems 444 | if (_strnicmp(Buffer, "exit\r\n", 6) == 0) 445 | ExitThread(0); 446 | 447 | 448 | // 449 | // If we got a CR, it's time to send what we've buffered up down to the 450 | // shell process. 451 | // SECURITY FIX: CW 12/27/04 Add BufferCnt size check. If we hit end of buffer, flush it 452 | if (RecvBuffer[0] == '\n' || RecvBuffer[0] == '\r' || BufferCnt > BUFFER_SIZE-1) { 453 | if (! WriteFile(Session->WritePipeHandle, Buffer, BufferCnt, 454 | &BytesWritten, NULL)) 455 | { 456 | break; 457 | } 458 | BufferCnt = 0; 459 | } 460 | } 461 | 462 | ExitThread(0); 463 | } 464 | 465 | #endif -------------------------------------------------------------------------------- /testbinaries/netcat/generic.h: -------------------------------------------------------------------------------- 1 | /* generic.h -- anything you don't #undef at the end remains in effect. 2 | The ONLY things that go in here are generic indicator flags; it's up 3 | to your programs to declare and call things based on those flags. 4 | 5 | You should only need to make changes via a minimal system-specific section 6 | at the end of this file. To build a new section, rip through this and 7 | check everything it mentions on your platform, and #undef that which needs 8 | it. If you generate a system-specific section you didn't find in here, 9 | please mail me a copy so I can update the "master". 10 | 11 | I realize I'm probably inventing another pseudo-standard here, but 12 | goddamnit, everybody ELSE has already, and I can't include all of their 13 | hairball schemes too. HAVE_xx conforms to the gnu/autoconf usage and 14 | seems to be the most common format. In fact, I dug a lot of these out 15 | of autoconf and tried to common them all together using "stupidh" to 16 | collect data from platforms. 17 | 18 | In disgust... _H* 940910, 941115. Pseudo-version: 1.1 */ 19 | 20 | #ifndef GENERIC_H /* only run through this once */ 21 | #define GENERIC_H 22 | 23 | /* =============================== */ 24 | /* System calls, lib routines, etc */ 25 | /* =============================== */ 26 | 27 | /* How does your system declare malloc, void or char? Usually void, but go 28 | ask the SunOS people why they had to be different... */ 29 | #define VOID_MALLOC 30 | 31 | /* notably from fwtk/firewall.h: posix locking? */ 32 | #define HAVE_FLOCK /* otherwise it's lockf() */ 33 | 34 | /* if you don't have setsid(), you might have setpgrp(). 35 | #define HAVE_SETSID 36 | 37 | /* random() is generally considered better than rand() */ 38 | /* xxx: rand48? */ 39 | #define HAVE_RANDOM 40 | 41 | /* if your machine doesn't have lstat(), it should have stat() [dos...] */ 42 | #define HAVE_LSTAT 43 | 44 | /* different kinds of term ioctls. How to recognize them, very roughly: 45 | sysv/POSIX_ME_HARDER: termio[s].h, struct termio[s], tty.c_*[] 46 | bsd/old stuff: sgtty.h, ioctl(TIOCSETP), sgttyb.sg_*, tchars.t_* 47 | #define HAVE_TERMIOS 48 | 49 | /* dbm vs ndbm */ 50 | #define HAVE_NDBM 51 | 52 | /* extended utmp/wtmp stuff. MOST machines still do NOT have this SV-ism */ 53 | #define UTMPX 54 | 55 | /* some systems have nice() which takes *relative* values... [resource.h] */ 56 | #define HAVE_SETPRIORITY 57 | 58 | /* a sysvism, I think, but ... */ 59 | #define HAVE_SYSINFO 60 | 61 | /* punted for now: setown / siocspgrp ... see firewall.h */ 62 | 63 | /* ============= */ 64 | /* Include files */ 65 | /* ============= */ 66 | 67 | /* Presence of these can be determined via a script that sniffs them 68 | out if you aren't sure. */ 69 | 70 | /* stdlib comes with most modern compilers, but ya never know */ 71 | #define HAVE_STDLIB_H 72 | 73 | /* not on a DOS box! */ 74 | #define HAVE_UNISTD_H 75 | 76 | /* stdarg is a weird one */ 77 | #define HAVE_STDARG_H 78 | 79 | /* dir.h or maybe ndir.h otherwise. */ 80 | #define HAVE_DIRENT_H 81 | 82 | /* string or strings */ 83 | #define HAVE_STRINGS_H 84 | 85 | /* if you don't have lastlog.h, what you want might be in login.h */ 86 | #define HAVE_LASTLOG_H 87 | 88 | /* predefines for _PATH_various */ 89 | #define HAVE_PATHS_H 90 | 91 | /* assorted others */ 92 | #define HAVE_PARAM_H 93 | #define HAVE_SYSMACROS_H /* in sys/! */ 94 | #define HAVE_TTYENT_H /* securetty et al */ 95 | 96 | /* ==================== */ 97 | 98 | /* Still maybe have to do something about the following, if it's even 99 | worth it. I just grepped a lot of these out of various code, without 100 | looking them up yet: 101 | 102 | #define HAVE_EINPROGRESS 103 | #define HAVE_F_SETOWN 104 | #define HAVE_SETENV ... now *there's* a hairy one; **environ is portable 105 | #define BIG_ENDIAN/little_endian ... *please* try to avoid this stupidity 106 | #define HAVE_GETUSERSHELL ... you could always pull it out of getpwent() 107 | #define HAVE_SETE[UG]ID ... lib or syscall, it varies on diff platforms 108 | #define HAVE_STRCHR ... should actually be handled by string/strings 109 | #define HAVE_PSTAT 110 | #define HAVE_ST_BLKSIZE ... a stat() thing? 111 | #define HAVE_IP_TOS 112 | #define HAVE_STRFTIME ... screw this, we should just INCLUDE one for lame 113 | old boxes that don't have it [sunos 3.x, early 4.x?] 114 | #define HAVE_VFPRINTF 115 | #define HAVE_SHADOW_PASSWD ... in its multitudinous schemes?? ... how 116 | about sumpin' like #define SHADOW_PASSWD_TYPE ... could get grody. 117 | #define SIG* ... what a swamp, punt for now; should all be in signal.h 118 | #define HAVE_STRCSPN ... see larry wall's comment in the fwtk regex code 119 | #define ULTRIX_AUTH ... bwahaha. 120 | #define HAVE_YP or NIS or whatever you wanna call it this week 121 | randomness about VARARGS?? 122 | 123 | There's also the issue about WHERE various .h files live, sys/ or otherwise. 124 | There's a BIG swamp lurking where network code of any sort lives. 125 | 126 | */ 127 | 128 | /* ======================== */ 129 | /* System-specific sections */ 130 | /* ======================== */ 131 | 132 | /* By turning OFF various bits of the above, you can customize for 133 | a given platform. /* 134 | 135 | /* DOS boxes, with MSC; you may need to adapt to a different compiler. */ 136 | #ifdef MSDOS 137 | #undef HAVE_FLOCK 138 | #undef HAVE_RANDOM 139 | #undef HAVE_LSTAT 140 | #undef HAVE_TERMIOS 141 | #undef UTMPX 142 | #undef HAVE_SYSINFO 143 | #undef HAVE_UNISTD_H 144 | #undef HAVE_DIRENT_H /* unless you have the k00l little wrapper from L5!! */ 145 | #undef HAVE_STRINGS_H 146 | #undef HAVE_LASTLOG_H 147 | #undef HAVE_PATHS_H 148 | #undef HAVE_PARAM_H 149 | #undef HAVE_SYSMACROS_H 150 | #undef HAVE_TTYENT_H 151 | #endif /* MSDOS */ 152 | 153 | /* buglix 4.x; dunno about 3.x on down. should be bsd4.2. */ 154 | #ifdef ULTRIX 155 | #undef UTMPX 156 | #undef HAVE_PATHS_H 157 | #undef HAVE_SYSMACROS_H 158 | #endif /* buglix */ 159 | 160 | /* some of this might still be broken on older sunoses */ 161 | #ifdef SUNOS 162 | #undef VOID_MALLOC 163 | #undef UTMPX 164 | #undef HAVE_PATHS_H 165 | #endif /* sunos */ 166 | 167 | /* "contact your vendor for a fix" */ 168 | #ifdef SOLARIS 169 | /* has UTMPX */ 170 | #undef HAVE_SETPRIORITY 171 | #undef HAVE_STRINGS_H /* this is genuinely the case, go figure */ 172 | #undef HAVE_PATHS_H 173 | #undef HAVE_TTYENT_H 174 | #endif /* SOLARIS */ 175 | 176 | /* whatever aix variant MIT had at the time */ 177 | #ifdef AIX 178 | #undef UTMPX 179 | #undef HAVE_LASTLOG_H 180 | #define HAVE_LOGIN_H /* "special", in the educational sense */ 181 | #endif /* aix */ 182 | 183 | /* linux, which is trying as desperately as the gnu folks can to be 184 | POSIXLY_CORRECT. I think I'm gonna hurl... */ 185 | #ifdef LINUX 186 | #undef UTMPX 187 | #undef HAVE_SYSINFO 188 | #undef HAVE_TTYENT_H 189 | #endif /* linux */ 190 | 191 | /* irix 5.x; may not be correct for earlier ones */ 192 | #ifdef IRIX 193 | /* wow, does irix really have everything?! */ 194 | #endif /* irix */ 195 | 196 | /* osf on alphas */ 197 | #ifdef OSF 198 | #undef UTMPX 199 | #endif /* osf */ 200 | 201 | /* they's some FUCKED UP paths in this one! */ 202 | #ifdef FREEBSD 203 | #undef UTMPX 204 | #undef HAVE_SYSINFO 205 | #undef HAVE_LASTLOG_H 206 | #undef HAVE_SYSMACROS_H 207 | #endif /* freebsd */ 208 | 209 | /* From the sidewinder site, of all places; may be unreliable */ 210 | #ifdef BSDI 211 | #undef UTMPX 212 | #undef HAVE_LASTLOG_H 213 | #undef HAVE_SYSMACROS_H 214 | #undef HAVE_TTYENT_H 215 | /* and their malloc.h was in sys/ ?! */ 216 | #endif /* bsdi */ 217 | 218 | /* netbsd/44lite, jives with amiga-netbsd from cactus */ 219 | #ifdef NETBSD 220 | #undef UTMPX 221 | #undef HAVE_SYSINFO 222 | #undef HAVE_LASTLOG_H 223 | #endif /* netbsd */ 224 | 225 | /* Make some "generic" assumptions if all else fails */ 226 | #ifdef GENERIC 227 | #undef HAVE_FLOCK 228 | #if defined(SYSV) && (SYSV < 4) /* TW leftover: old SV doesnt have symlinks */ 229 | #undef HAVE_LSTAT 230 | #endif /* old SYSV */ 231 | #undef HAVE_TERMIOS 232 | #undef UTMPX 233 | #undef HAVE_PATHS_H 234 | #endif /* generic */ 235 | 236 | /* ================ */ 237 | #endif /* GENERIC_H */ 238 | -------------------------------------------------------------------------------- /testbinaries/netcat/getopt.c: -------------------------------------------------------------------------------- 1 | /* Getopt for GNU. 2 | NOTE: getopt is now part of the C library, so if you don't know what 3 | "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu 4 | before changing it! 5 | 6 | Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94 7 | Free Software Foundation, Inc. 8 | 9 | This file is part of the GNU C Library. Its master source is NOT part of 10 | the C library, however. The master source lives in /gd/gnu/lib. 11 | 12 | The GNU C Library is free software; you can redistribute it and/or 13 | modify it under the terms of the GNU Library General Public License as 14 | published by the Free Software Foundation; either version 2 of the 15 | License, or (at your option) any later version. 16 | 17 | The GNU C Library is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | Library General Public License for more details. 21 | 22 | You should have received a copy of the GNU Library General Public 23 | License along with the GNU C Library; see the file COPYING.LIB. If 24 | not, write to the Free Software Foundation, Inc., 675 Mass Ave, 25 | Cambridge, MA 02139, USA. */ 26 | 27 | /* This tells Alpha OSF/1 not to define a getopt prototype in . 28 | Ditto for AIX 3.2 and . */ 29 | #ifndef _NO_PROTO 30 | #define _NO_PROTO 31 | #endif 32 | 33 | #define _CRT_SECURE_NO_WARNINGS 34 | #define itoa _itoa 35 | 36 | #ifdef HAVE_CONFIG_H 37 | #include 38 | #endif 39 | 40 | #if !defined (__STDC__) || !__STDC__ 41 | /* This is a separate conditional since some stdc systems 42 | reject `defined (const)'. */ 43 | #ifndef const 44 | #define const 45 | #endif 46 | #endif 47 | 48 | #include 49 | 50 | #ifdef WIN32 51 | #include 52 | #endif 53 | 54 | /* Comment out all this code if we are using the GNU C Library, and are not 55 | actually compiling the library itself. This code is part of the GNU C 56 | Library, but also included in many other GNU distributions. Compiling 57 | and linking in this code is a waste when using the GNU C library 58 | (especially if it is a shared library). Rather than having every GNU 59 | program understand `configure --with-gnu-libc' and omit the object files, 60 | it is simpler to just do this in the source for each such file. */ 61 | 62 | #if defined (_LIBC) || !defined (__GNU_LIBRARY__) 63 | 64 | 65 | /* This needs to come after some library #include 66 | to get __GNU_LIBRARY__ defined. */ 67 | #ifdef __GNU_LIBRARY__ 68 | /* Don't include stdlib.h for non-GNU C libraries because some of them 69 | contain conflicting prototypes for getopt. */ 70 | #include 71 | #endif /* GNU C library. */ 72 | 73 | /* This version of `getopt' appears to the caller like standard Unix `getopt' 74 | but it behaves differently for the user, since it allows the user 75 | to intersperse the options with the other arguments. 76 | 77 | As `getopt' works, it permutes the elements of ARGV so that, 78 | when it is done, all the options precede everything else. Thus 79 | all application programs are extended to handle flexible argument order. 80 | 81 | Setting the environment variable POSIXLY_CORRECT disables permutation. 82 | Then the behavior is completely standard. 83 | 84 | GNU application programs can use a third alternative mode in which 85 | they can distinguish the relative order of options and other arguments. */ 86 | 87 | #include "getopt.h" 88 | 89 | /* For communication from `getopt' to the caller. 90 | When `getopt' finds an option that takes an argument, 91 | the argument value is returned here. 92 | Also, when `ordering' is RETURN_IN_ORDER, 93 | each non-option ARGV-element is returned here. */ 94 | 95 | char *optarg = NULL; 96 | 97 | /* Index in ARGV of the next element to be scanned. 98 | This is used for communication to and from the caller 99 | and for communication between successive calls to `getopt'. 100 | 101 | On entry to `getopt', zero means this is the first call; initialize. 102 | 103 | When `getopt' returns EOF, this is the index of the first of the 104 | non-option elements that the caller should itself scan. 105 | 106 | Otherwise, `optind' communicates from one call to the next 107 | how much of ARGV has been scanned so far. */ 108 | 109 | /* XXX 1003.2 says this must be 1 before any call. */ 110 | int optind = 0; 111 | 112 | /* The next char to be scanned in the option-element 113 | in which the last option character we returned was found. 114 | This allows us to pick up the scan where we left off. 115 | 116 | If this is zero, or a null string, it means resume the scan 117 | by advancing to the next ARGV-element. */ 118 | 119 | static char *nextchar; 120 | 121 | /* Callers store zero here to inhibit the error message 122 | for unrecognized options. */ 123 | 124 | int opterr = 1; 125 | 126 | /* Set to an option character which was unrecognized. 127 | This must be initialized on some systems to avoid linking in the 128 | system's own getopt implementation. */ 129 | 130 | int optopt = '?'; 131 | 132 | /* Describe how to deal with options that follow non-option ARGV-elements. 133 | 134 | If the caller did not specify anything, 135 | the default is REQUIRE_ORDER if the environment variable 136 | POSIXLY_CORRECT is defined, PERMUTE otherwise. 137 | 138 | REQUIRE_ORDER means don't recognize them as options; 139 | stop option processing when the first non-option is seen. 140 | This is what Unix does. 141 | This mode of operation is selected by either setting the environment 142 | variable POSIXLY_CORRECT, or using `+' as the first character 143 | of the list of option characters. 144 | 145 | PERMUTE is the default. We permute the contents of ARGV as we scan, 146 | so that eventually all the non-options are at the end. This allows options 147 | to be given in any order, even with programs that were not written to 148 | expect this. 149 | 150 | RETURN_IN_ORDER is an option available to programs that were written 151 | to expect options and other ARGV-elements in any order and that care about 152 | the ordering of the two. We describe each non-option ARGV-element 153 | as if it were the argument of an option with character code 1. 154 | Using `-' as the first character of the list of option characters 155 | selects this mode of operation. 156 | 157 | The special argument `--' forces an end of option-scanning regardless 158 | of the value of `ordering'. In the case of RETURN_IN_ORDER, only 159 | `--' can cause `getopt' to return EOF with `optind' != ARGC. */ 160 | 161 | static enum 162 | { 163 | REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER 164 | } ordering; 165 | 166 | /* Value of POSIXLY_CORRECT environment variable. */ 167 | static char *posixly_correct; 168 | 169 | #ifdef __GNU_LIBRARY__ 170 | /* We want to avoid inclusion of string.h with non-GNU libraries 171 | because there are many ways it can cause trouble. 172 | On some systems, it contains special magic macros that don't work 173 | in GCC. */ 174 | #include 175 | #define my_index strchr 176 | #else 177 | 178 | /* Avoid depending on library functions or files 179 | whose names are inconsistent. */ 180 | 181 | char *getenv (); 182 | 183 | static char * 184 | my_index (str, chr) 185 | const char *str; 186 | int chr; 187 | { 188 | while (*str) 189 | { 190 | if (*str == chr) 191 | return (char *) str; 192 | str++; 193 | } 194 | return 0; 195 | } 196 | 197 | /* If using GCC, we can safely declare strlen this way. 198 | If not using GCC, it is ok not to declare it. */ 199 | #ifdef __GNUC__ 200 | /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. 201 | That was relevant to code that was here before. */ 202 | #if !defined (__STDC__) || !__STDC__ 203 | /* gcc with -traditional declares the built-in strlen to return int, 204 | and has done so at least since version 2.4.5. -- rms. */ 205 | extern int strlen (const char *); 206 | #endif /* not __STDC__ */ 207 | #endif /* __GNUC__ */ 208 | 209 | #endif /* not __GNU_LIBRARY__ */ 210 | 211 | /* Handle permutation of arguments. */ 212 | 213 | /* Describe the part of ARGV that contains non-options that have 214 | been skipped. `first_nonopt' is the index in ARGV of the first of them; 215 | `last_nonopt' is the index after the last of them. */ 216 | 217 | static int first_nonopt; 218 | static int last_nonopt; 219 | 220 | /* Exchange two adjacent subsequences of ARGV. 221 | One subsequence is elements [first_nonopt,last_nonopt) 222 | which contains all the non-options that have been skipped so far. 223 | The other is elements [last_nonopt,optind), which contains all 224 | the options processed since those non-options were skipped. 225 | 226 | `first_nonopt' and `last_nonopt' are relocated so that they describe 227 | the new indices of the non-options in ARGV after they are moved. */ 228 | 229 | static void 230 | exchange (argv) 231 | char **argv; 232 | { 233 | int bottom = first_nonopt; 234 | int middle = last_nonopt; 235 | int top = optind; 236 | char *tem; 237 | 238 | /* Exchange the shorter segment with the far end of the longer segment. 239 | That puts the shorter segment into the right place. 240 | It leaves the longer segment in the right place overall, 241 | but it consists of two parts that need to be swapped next. */ 242 | 243 | while (top > middle && middle > bottom) 244 | { 245 | if (top - middle > middle - bottom) 246 | { 247 | /* Bottom segment is the short one. */ 248 | int len = middle - bottom; 249 | register int i; 250 | 251 | /* Swap it with the top part of the top segment. */ 252 | for (i = 0; i < len; i++) 253 | { 254 | tem = argv[bottom + i]; 255 | argv[bottom + i] = argv[top - (middle - bottom) + i]; 256 | argv[top - (middle - bottom) + i] = tem; 257 | } 258 | /* Exclude the moved bottom segment from further swapping. */ 259 | top -= len; 260 | } 261 | else 262 | { 263 | /* Top segment is the short one. */ 264 | int len = top - middle; 265 | register int i; 266 | 267 | /* Swap it with the bottom part of the bottom segment. */ 268 | for (i = 0; i < len; i++) 269 | { 270 | tem = argv[bottom + i]; 271 | argv[bottom + i] = argv[middle + i]; 272 | argv[middle + i] = tem; 273 | } 274 | /* Exclude the moved top segment from further swapping. */ 275 | bottom += len; 276 | } 277 | } 278 | 279 | /* Update records for the slots the non-options now occupy. */ 280 | 281 | first_nonopt += (optind - last_nonopt); 282 | last_nonopt = optind; 283 | } 284 | 285 | /* Initialize the internal data when the first call is made. */ 286 | 287 | static const char * 288 | _getopt_initialize (optstring) 289 | const char *optstring; 290 | { 291 | /* Start processing options with ARGV-element 1 (since ARGV-element 0 292 | is the program name); the sequence of previously skipped 293 | non-option ARGV-elements is empty. */ 294 | 295 | first_nonopt = last_nonopt = optind = 1; 296 | 297 | nextchar = NULL; 298 | 299 | posixly_correct = getenv ("POSIXLY_CORRECT"); 300 | 301 | /* Determine how to handle the ordering of options and nonoptions. */ 302 | 303 | if (optstring[0] == '-') 304 | { 305 | ordering = RETURN_IN_ORDER; 306 | ++optstring; 307 | } 308 | else if (optstring[0] == '+') 309 | { 310 | ordering = REQUIRE_ORDER; 311 | ++optstring; 312 | } 313 | else if (posixly_correct != NULL) 314 | ordering = REQUIRE_ORDER; 315 | else 316 | ordering = PERMUTE; 317 | 318 | return optstring; 319 | } 320 | 321 | /* Scan elements of ARGV (whose length is ARGC) for option characters 322 | given in OPTSTRING. 323 | 324 | If an element of ARGV starts with '-', and is not exactly "-" or "--", 325 | then it is an option element. The characters of this element 326 | (aside from the initial '-') are option characters. If `getopt' 327 | is called repeatedly, it returns successively each of the option characters 328 | from each of the option elements. 329 | 330 | If `getopt' finds another option character, it returns that character, 331 | updating `optind' and `nextchar' so that the next call to `getopt' can 332 | resume the scan with the following option character or ARGV-element. 333 | 334 | If there are no more option characters, `getopt' returns `EOF'. 335 | Then `optind' is the index in ARGV of the first ARGV-element 336 | that is not an option. (The ARGV-elements have been permuted 337 | so that those that are not options now come last.) 338 | 339 | OPTSTRING is a string containing the legitimate option characters. 340 | If an option character is seen that is not listed in OPTSTRING, 341 | return '?' after printing an error message. If you set `opterr' to 342 | zero, the error message is suppressed but we still return '?'. 343 | 344 | If a char in OPTSTRING is followed by a colon, that means it wants an arg, 345 | so the following text in the same ARGV-element, or the text of the following 346 | ARGV-element, is returned in `optarg'. Two colons mean an option that 347 | wants an optional arg; if there is text in the current ARGV-element, 348 | it is returned in `optarg', otherwise `optarg' is set to zero. 349 | 350 | If OPTSTRING starts with `-' or `+', it requests different methods of 351 | handling the non-option ARGV-elements. 352 | See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. 353 | 354 | Long-named options begin with `--' instead of `-'. 355 | Their names may be abbreviated as long as the abbreviation is unique 356 | or is an exact match for some defined option. If they have an 357 | argument, it follows the option name in the same ARGV-element, separated 358 | from the option name by a `=', or else the in next ARGV-element. 359 | When `getopt' finds a long-named option, it returns 0 if that option's 360 | `flag' field is nonzero, the value of the option's `val' field 361 | if the `flag' field is zero. 362 | 363 | The elements of ARGV aren't really const, because we permute them. 364 | But we pretend they're const in the prototype to be compatible 365 | with other systems. 366 | 367 | LONGOPTS is a vector of `struct option' terminated by an 368 | element containing a name which is zero. 369 | 370 | LONGIND returns the index in LONGOPT of the long-named option found. 371 | It is only valid when a long-named option has been found by the most 372 | recent call. 373 | 374 | If LONG_ONLY is nonzero, '-' as well as '--' can introduce 375 | long-named options. */ 376 | 377 | int 378 | _getopt_internal (argc, argv, optstring, longopts, longind, long_only) 379 | int argc; 380 | char *const *argv; 381 | const char *optstring; 382 | const struct option *longopts; 383 | int *longind; 384 | int long_only; 385 | { 386 | optarg = NULL; 387 | 388 | if (optind == 0) 389 | optstring = _getopt_initialize (optstring); 390 | 391 | if (nextchar == NULL || *nextchar == '\0') 392 | { 393 | /* Advance to the next ARGV-element. */ 394 | 395 | if (ordering == PERMUTE) 396 | { 397 | /* If we have just processed some options following some non-options, 398 | exchange them so that the options come first. */ 399 | 400 | if (first_nonopt != last_nonopt && last_nonopt != optind) 401 | exchange ((char **) argv); 402 | else if (last_nonopt != optind) 403 | first_nonopt = optind; 404 | 405 | /* Skip any additional non-options 406 | and extend the range of non-options previously skipped. */ 407 | 408 | while (optind < argc 409 | && (argv[optind][0] != '-' || argv[optind][1] == '\0')) 410 | optind++; 411 | last_nonopt = optind; 412 | } 413 | 414 | /* The special ARGV-element `--' means premature end of options. 415 | Skip it like a null option, 416 | then exchange with previous non-options as if it were an option, 417 | then skip everything else like a non-option. */ 418 | 419 | if (optind != argc && !strcmp (argv[optind], "--")) 420 | { 421 | optind++; 422 | 423 | if (first_nonopt != last_nonopt && last_nonopt != optind) 424 | exchange ((char **) argv); 425 | else if (first_nonopt == last_nonopt) 426 | first_nonopt = optind; 427 | last_nonopt = argc; 428 | 429 | optind = argc; 430 | } 431 | 432 | /* If we have done all the ARGV-elements, stop the scan 433 | and back over any non-options that we skipped and permuted. */ 434 | 435 | if (optind == argc) 436 | { 437 | /* Set the next-arg-index to point at the non-options 438 | that we previously skipped, so the caller will digest them. */ 439 | if (first_nonopt != last_nonopt) 440 | optind = first_nonopt; 441 | return EOF; 442 | } 443 | 444 | /* If we have come to a non-option and did not permute it, 445 | either stop the scan or describe it to the caller and pass it by. */ 446 | 447 | if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) 448 | { 449 | if (ordering == REQUIRE_ORDER) 450 | return EOF; 451 | optarg = argv[optind++]; 452 | return 1; 453 | } 454 | 455 | /* We have found another option-ARGV-element. 456 | Skip the initial punctuation. */ 457 | 458 | nextchar = (argv[optind] + 1 459 | + (longopts != NULL && argv[optind][1] == '-')); 460 | } 461 | 462 | /* Decode the current option-ARGV-element. */ 463 | 464 | /* Check whether the ARGV-element is a long option. 465 | 466 | If long_only and the ARGV-element has the form "-f", where f is 467 | a valid short option, don't consider it an abbreviated form of 468 | a long option that starts with f. Otherwise there would be no 469 | way to give the -f short option. 470 | 471 | On the other hand, if there's a long option "fubar" and 472 | the ARGV-element is "-fu", do consider that an abbreviation of 473 | the long option, just like "--fu", and not "-f" with arg "u". 474 | 475 | This distinction seems to be the most useful approach. */ 476 | 477 | if (longopts != NULL 478 | && (argv[optind][1] == '-' 479 | || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) 480 | { 481 | char *nameend; 482 | const struct option *p; 483 | const struct option *pfound = NULL; 484 | int exact = 0; 485 | int ambig = 0; 486 | int indfound; 487 | int option_index; 488 | 489 | for (nameend = nextchar; *nameend && *nameend != '='; nameend++) 490 | /* Do nothing. */ ; 491 | 492 | /* Test all long options for either exact match 493 | or abbreviated matches. */ 494 | for (p = longopts, option_index = 0; p->name; p++, option_index++) 495 | if (!strncmp (p->name, nextchar, nameend - nextchar)) 496 | { 497 | if ((unsigned int)(nameend - nextchar) == (unsigned int)strlen (p->name)) 498 | { 499 | /* Exact match found. */ 500 | pfound = p; 501 | indfound = option_index; 502 | exact = 1; 503 | break; 504 | } 505 | else if (pfound == NULL) 506 | { 507 | /* First nonexact match found. */ 508 | pfound = p; 509 | indfound = option_index; 510 | } 511 | else 512 | /* Second or later nonexact match found. */ 513 | ambig = 1; 514 | } 515 | 516 | if (ambig && !exact) 517 | { 518 | if (opterr) 519 | fprintf (stderr, "%s: option `%s' is ambiguous\n", 520 | argv[0], argv[optind]); 521 | nextchar += strlen (nextchar); 522 | optind++; 523 | return '?'; 524 | } 525 | 526 | if (pfound != NULL) 527 | { 528 | option_index = indfound; 529 | optind++; 530 | if (*nameend) 531 | { 532 | /* Don't test has_arg with >, because some C compilers don't 533 | allow it to be used on enums. */ 534 | if (pfound->has_arg) 535 | optarg = nameend + 1; 536 | else 537 | { 538 | if (opterr) 539 | { 540 | if (argv[optind - 1][1] == '-') 541 | /* --option */ 542 | fprintf (stderr, 543 | "%s: option `--%s' doesn't allow an argument\n", 544 | argv[0], pfound->name); 545 | else 546 | /* +option or -option */ 547 | fprintf (stderr, 548 | "%s: option `%c%s' doesn't allow an argument\n", 549 | argv[0], argv[optind - 1][0], pfound->name); 550 | } 551 | nextchar += strlen (nextchar); 552 | return '?'; 553 | } 554 | } 555 | else if (pfound->has_arg == 1) 556 | { 557 | if (optind < argc) 558 | optarg = argv[optind++]; 559 | else 560 | { 561 | if (opterr) 562 | fprintf (stderr, "%s: option `%s' requires an argument\n", 563 | argv[0], argv[optind - 1]); 564 | nextchar += strlen (nextchar); 565 | return optstring[0] == ':' ? ':' : '?'; 566 | } 567 | } 568 | nextchar += strlen (nextchar); 569 | if (longind != NULL) 570 | *longind = option_index; 571 | if (pfound->flag) 572 | { 573 | *(pfound->flag) = pfound->val; 574 | return 0; 575 | } 576 | return pfound->val; 577 | } 578 | 579 | /* Can't find it as a long option. If this is not getopt_long_only, 580 | or the option starts with '--' or is not a valid short 581 | option, then it's an error. 582 | Otherwise interpret it as a short option. */ 583 | if (!long_only || argv[optind][1] == '-' 584 | || my_index (optstring, *nextchar) == NULL) 585 | { 586 | if (opterr) 587 | { 588 | if (argv[optind][1] == '-') 589 | /* --option */ 590 | fprintf (stderr, "%s: unrecognized option `--%s'\n", 591 | argv[0], nextchar); 592 | else 593 | /* +option or -option */ 594 | fprintf (stderr, "%s: unrecognized option `%c%s'\n", 595 | argv[0], argv[optind][0], nextchar); 596 | } 597 | nextchar = (char *) ""; 598 | optind++; 599 | return '?'; 600 | } 601 | } 602 | 603 | /* Look at and handle the next short option-character. */ 604 | 605 | { 606 | char c = *nextchar++; 607 | char *temp = my_index (optstring, c); 608 | 609 | /* Increment `optind' when we start to process its last character. */ 610 | if (*nextchar == '\0') 611 | ++optind; 612 | 613 | if (temp == NULL || c == ':') 614 | { 615 | if (opterr) 616 | { 617 | if (posixly_correct) 618 | /* 1003.2 specifies the format of this message. */ 619 | fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); 620 | else 621 | fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c); 622 | } 623 | optopt = c; 624 | return '?'; 625 | } 626 | if (temp[1] == ':') 627 | { 628 | if (temp[2] == ':') 629 | { 630 | /* This is an option that accepts an argument optionally. */ 631 | if (*nextchar != '\0') 632 | { 633 | optarg = nextchar; 634 | optind++; 635 | } 636 | else 637 | optarg = NULL; 638 | nextchar = NULL; 639 | } 640 | else 641 | { 642 | /* This is an option that requires an argument. */ 643 | if (*nextchar != '\0') 644 | { 645 | optarg = nextchar; 646 | /* If we end this ARGV-element by taking the rest as an arg, 647 | we must advance to the next element now. */ 648 | optind++; 649 | } 650 | else if (optind == argc) 651 | { 652 | if (opterr) 653 | { 654 | /* 1003.2 specifies the format of this message. */ 655 | fprintf (stderr, "%s: option requires an argument -- %c\n", 656 | argv[0], c); 657 | } 658 | optopt = c; 659 | if (optstring[0] == ':') 660 | c = ':'; 661 | else 662 | c = '?'; 663 | } 664 | else 665 | /* We already incremented `optind' once; 666 | increment it again when taking next ARGV-elt as argument. */ 667 | optarg = argv[optind++]; 668 | nextchar = NULL; 669 | } 670 | } 671 | return c; 672 | } 673 | } 674 | 675 | int 676 | getopt (argc, argv, optstring) 677 | int argc; 678 | char *const *argv; 679 | const char *optstring; 680 | { 681 | return _getopt_internal (argc, argv, optstring, 682 | (const struct option *) 0, 683 | (int *) 0, 684 | 0); 685 | } 686 | 687 | #endif /* _LIBC or not __GNU_LIBRARY__. */ 688 | 689 | #ifdef TEST 690 | 691 | /* Compile with -DTEST to make an executable for use in testing 692 | the above definition of `getopt'. */ 693 | 694 | int 695 | main (argc, argv) 696 | int argc; 697 | char **argv; 698 | { 699 | int c; 700 | int digit_optind = 0; 701 | 702 | while (1) 703 | { 704 | int this_option_optind = optind ? optind : 1; 705 | 706 | c = getopt (argc, argv, "abc:d:0123456789"); 707 | if (c == EOF) 708 | break; 709 | 710 | switch (c) 711 | { 712 | case '0': 713 | case '1': 714 | case '2': 715 | case '3': 716 | case '4': 717 | case '5': 718 | case '6': 719 | case '7': 720 | case '8': 721 | case '9': 722 | if (digit_optind != 0 && digit_optind != this_option_optind) 723 | printf ("digits occur in two different argv-elements.\n"); 724 | digit_optind = this_option_optind; 725 | printf ("option %c\n", c); 726 | break; 727 | 728 | case 'a': 729 | printf ("option a\n"); 730 | break; 731 | 732 | case 'b': 733 | printf ("option b\n"); 734 | break; 735 | 736 | case 'c': 737 | printf ("option c with value `%s'\n", optarg); 738 | break; 739 | 740 | case '?': 741 | break; 742 | 743 | default: 744 | printf ("?? getopt returned character code 0%o ??\n", c); 745 | } 746 | } 747 | 748 | if (optind < argc) 749 | { 750 | printf ("non-option ARGV-elements: "); 751 | while (optind < argc) 752 | printf ("%s ", argv[optind++]); 753 | printf ("\n"); 754 | } 755 | 756 | exit (0); 757 | } 758 | 759 | #endif /* TEST */ 760 | -------------------------------------------------------------------------------- /testbinaries/netcat/getopt.h: -------------------------------------------------------------------------------- 1 | /* Declarations for getopt. 2 | Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc. 3 | 4 | This file is part of the GNU C Library. Its master source is NOT part of 5 | the C library, however. The master source lives in /gd/gnu/lib. 6 | 7 | The GNU C Library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Library General Public License as 9 | published by the Free Software Foundation; either version 2 of the 10 | License, or (at your option) any later version. 11 | 12 | The GNU C Library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Library General Public License for more details. 16 | 17 | You should have received a copy of the GNU Library General Public 18 | License along with the GNU C Library; see the file COPYING.LIB. If 19 | not, write to the Free Software Foundation, Inc., 675 Mass Ave, 20 | Cambridge, MA 02139, USA. */ 21 | 22 | #ifndef _GETOPT_H 23 | #define _GETOPT_H 1 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* For communication from `getopt' to the caller. 30 | When `getopt' finds an option that takes an argument, 31 | the argument value is returned here. 32 | Also, when `ordering' is RETURN_IN_ORDER, 33 | each non-option ARGV-element is returned here. */ 34 | 35 | extern char *optarg; 36 | 37 | /* Index in ARGV of the next element to be scanned. 38 | This is used for communication to and from the caller 39 | and for communication between successive calls to `getopt'. 40 | 41 | On entry to `getopt', zero means this is the first call; initialize. 42 | 43 | When `getopt' returns EOF, this is the index of the first of the 44 | non-option elements that the caller should itself scan. 45 | 46 | Otherwise, `optind' communicates from one call to the next 47 | how much of ARGV has been scanned so far. */ 48 | 49 | extern int optind; 50 | 51 | /* Callers store zero here to inhibit the error message `getopt' prints 52 | for unrecognized options. */ 53 | 54 | extern int opterr; 55 | 56 | /* Set to an option character which was unrecognized. */ 57 | 58 | extern int optopt; 59 | 60 | /* Describe the long-named options requested by the application. 61 | The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector 62 | of `struct option' terminated by an element containing a name which is 63 | zero. 64 | 65 | The field `has_arg' is: 66 | no_argument (or 0) if the option does not take an argument, 67 | required_argument (or 1) if the option requires an argument, 68 | optional_argument (or 2) if the option takes an optional argument. 69 | 70 | If the field `flag' is not NULL, it points to a variable that is set 71 | to the value given in the field `val' when the option is found, but 72 | left unchanged if the option is not found. 73 | 74 | To have a long-named option do something other than set an `int' to 75 | a compiled-in constant, such as set a value from `optarg', set the 76 | option's `flag' field to zero and its `val' field to a nonzero 77 | value (the equivalent single-letter option character, if there is 78 | one). For long options that have a zero `flag' field, `getopt' 79 | returns the contents of the `val' field. */ 80 | 81 | struct option 82 | { 83 | #if defined (__STDC__) && __STDC__ 84 | const char *name; 85 | #else 86 | char *name; 87 | #endif 88 | /* has_arg can't be an enum because some compilers complain about 89 | type mismatches in all the code that assumes it is an int. */ 90 | int has_arg; 91 | int *flag; 92 | int val; 93 | }; 94 | 95 | /* Names for the values of the `has_arg' field of `struct option'. */ 96 | 97 | #define no_argument 0 98 | #define required_argument 1 99 | #define optional_argument 2 100 | 101 | #if defined (__STDC__) && __STDC__ 102 | #ifdef __GNU_LIBRARY__ 103 | /* Many other libraries have conflicting prototypes for getopt, with 104 | differences in the consts, in stdlib.h. To avoid compilation 105 | errors, only prototype getopt for the GNU C library. */ 106 | extern int getopt (int argc, char *const *argv, const char *shortopts); 107 | #else /* not __GNU_LIBRARY__ */ 108 | extern int getopt (); 109 | #endif /* __GNU_LIBRARY__ */ 110 | extern int getopt_long (int argc, char *const *argv, const char *shortopts, 111 | const struct option *longopts, int *longind); 112 | extern int getopt_long_only (int argc, char *const *argv, 113 | const char *shortopts, 114 | const struct option *longopts, int *longind); 115 | 116 | /* Internal only. Users should not call this directly. */ 117 | extern int _getopt_internal (int argc, char *const *argv, 118 | const char *shortopts, 119 | const struct option *longopts, int *longind, 120 | int long_only); 121 | #else /* not __STDC__ */ 122 | extern int getopt (); 123 | extern int getopt_long (); 124 | extern int getopt_long_only (); 125 | 126 | extern int _getopt_internal (); 127 | #endif /* __STDC__ */ 128 | 129 | #ifdef __cplusplus 130 | } 131 | #endif 132 | 133 | #endif /* _GETOPT_H */ 134 | -------------------------------------------------------------------------------- /testbinaries/netcat/license.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /testbinaries/netcat/netcat.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {05A97D23-287B-4D6C-93FC-4BDD1EADC6E4} 15 | netcat 16 | 17 | 18 | 19 | Application 20 | true 21 | MultiByte 22 | 23 | 24 | Application 25 | false 26 | true 27 | MultiByte 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | false 41 | 42 | 43 | 44 | Level3 45 | Disabled 46 | /nologo /ML /W3 /GX /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "TELNET" /D "GAPING_SECURITY_HOLE" /YX /FD /c %(AdditionalOptions) 47 | EnableFastChecks 48 | 49 | 50 | true 51 | $(SolutionDir)..\$(TargetName)$(TargetExt) 52 | 53 | 54 | 55 | 56 | Level3 57 | Disabled 58 | true 59 | true 60 | false 61 | CompileAsC 62 | /nologo /ML /W3 /GX /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "TELNET" /D "GAPING_SECURITY_HOLE" /YX /FD /c %(AdditionalOptions) 63 | 64 | 65 | false 66 | true 67 | true 68 | $(SolutionDir)..\$(TargetName)$(TargetExt) 69 | "D:\Dropbox\CPP\msvcrt-compat\msvcrt.lib";"D:\Dropbox\CPP\msvcrt-compat\ntdll.lib";%(AdditionalDependencies) 70 | Console 71 | Main 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /testbinaries/netcat/netcat.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | -------------------------------------------------------------------------------- /testbinaries/netcat/netcat.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /testbinaries/netcat/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | UPDATE 12/27/04 security fix in -e option for Windows 3 | 4 | Netcat 1.11 for NT - nc111nt.zip 5 | 6 | The original version of Netcat was written by *hobbit* 7 | The NT version was done by Weld Pond 8 | 9 | Netcat for NT is the tcp/ip "Swiss Army knife" that never made it into any 10 | of the resource kits. It has proved to be an extremely versatile tool on 11 | the unix platform. So why should NT always be unix's poor cousin when it 12 | comes to tcp/ip testing and exploration? I bet many NT admins out there 13 | keep a unix box around to use tools such as Netcat or to test their systems 14 | with the unix version of an NT vulnerability exploit. With Netcat for NT 15 | part of that feeling disempowerment is over. 16 | 17 | Included with this release is Hobbit's original description of the powers 18 | of Netcat. In this document I will briefly describe some of the things an 19 | NT admin might want to do and know about with Netcat on NT. For more 20 | detailed technical information please read hobbit.txt included in the 21 | nc11nt.zip archive. 22 | 23 | Basic Features 24 | 25 | * Outbound or inbound connections, TCP or UDP, to or from any ports 26 | * Full DNS forward/reverse checking, with appropriate warnings 27 | * Ability to use any local source port 28 | * Ability to use any locally-configured network source address 29 | * Built-in port-scanning capabilities, with randomizer 30 | * Can read command line arguments from standard input 31 | * Slow-send mode, one line every N seconds 32 | * Hex dump of transmitted and received data 33 | * Ability to let another program service established 34 | connections 35 | * Telnet-options responder 36 | 37 | New for NT 38 | 39 | * Ability to run in the background without a console window 40 | * Ability to restart as a single-threaded server to handle a new 41 | connection 42 | 43 | 44 | A simple example of using Netcat is to pull down a web page from a web 45 | server. With Netcat you get to see the full HTTP header so you can see 46 | which web server a particular site is running. 47 | 48 | Since NT has a rather anemic command processor, some of the things that are 49 | easy in unix may be a bit more clunky in NT. For the web page example first 50 | create a file get.txt that contains the following line and then a blank 51 | line: 52 | 53 | GET / HTTP/1.0 54 | 55 | To use Netcat to retrieve the home page of a web site use the command: 56 | nc -v www.website.com 80 < get.txt 57 | 58 | You will see Netcat make a connection to port 80, send the text contained 59 | in the file get.txt, and then output the web server's response to stdout. 60 | The -v is for verbose. It tells you a little info about the connection 61 | when it starts. 62 | 63 | It is a bit easier to just open the connection and then type at the console 64 | to do the same thing. 65 | nc -v www.website.com 80 66 | 67 | Then just type in GET / HTTP/1.0 and hit a couple of returns. You will 68 | see the same thing as above. 69 | 70 | A far more exciting thing to do is to get a quick shell going on a remote 71 | machine by using the -l or "listen" option and the -e or "execute" 72 | option. You run Netcat listening on particular port for a connection. 73 | When a connection is made, Netcat executes the program of your choice 74 | and connects the stdin and stdout of the program to the network connection. 75 | 76 | nc -l -p 23 -t -e cmd.exe 77 | 78 | will get Netcat listening on port 23 (telnet). When it gets connected to 79 | by a client it will spawn a shell (cmd.exe). The -t option tells Netcat 80 | to handle any telnet negotiation the client might expect. 81 | 82 | This will allow you to telnet to the machine you have Netcat listening on 83 | and get a cmd.exe shell when you connect. You could just as well use 84 | Netcat instead of telnet: 85 | 86 | nc xxx.xxx.xxx.xxx 23 87 | 88 | will get the job done. There is no authentication on the listening side 89 | so be a bit careful here. The shell is running with the permissions of the 90 | process that started Netcat so be very careful. If you were to use the 91 | AT program to schedule Netcat to run listening on a port with the 92 | -e cmd.exe option, when you connected you would get a shell with user 93 | NT AUTHORITY\SYSTEM. 94 | 95 | The beauty of Netcat really shines when you realize that you can get it 96 | listening on ANY port doing the same thing. Do a little exploring and 97 | see if the firewall you may be behind lets port 53 through. Run Netcat 98 | listening behind the firewall on port 53. 99 | 100 | nc -L -p 53 -e cmd.exe 101 | 102 | Then from outside the firewall connect to the listening machine: 103 | 104 | nc -v xxx.xxx.xxx.xx 53 105 | 106 | If you get a command prompt then you are executing commands on the 107 | listening machine. Use 'exit' at the command prompt for a clean 108 | disconnect. The -L (note the capital L) option will restart Netcat with 109 | the same command line when the connection is terminated. This way you can 110 | connect over and over to the same Netcat process. 111 | 112 | A new feature for the NT version is the -d or detach from console flag. 113 | This will let Netcat run without an ugly console window cluttering up the 114 | screen or showing up in the task list. 115 | 116 | You can even get Netcat to listen on the NETBIOS ports that are probably 117 | running on most NT machines. This way you can get a connection to a 118 | machine that may have port filtering enabled in the TCP/IP Security Network 119 | control panel. Unlike Unix, NT does not seem to have any security around 120 | which ports that user programs are allowed to bind to. This means any 121 | user can run a program that will bind to the NETBIOS ports. 122 | 123 | You will need to bind "in front of" some services that may already be 124 | listening on those ports. An example is the NETBIOS Session Service that 125 | is running on port 139 of NT machines that are sharing files. You need 126 | to bind to a specific source address (one of the IP addresses of the 127 | machine) to accomplish this. This gives Netcat priority over the NETBIOS 128 | service which is at a lower priority because it is bound to ANY IP address. 129 | This is done with the Netcat -s option: 130 | 131 | nc -v -L -e cmd.exe -p 139 -s xxx.xxx.xxx.xxx 132 | 133 | Now you can connect to the machine on port 139 and Netcat will field 134 | the connection before NETBIOS does. You have effectively shut off 135 | file sharing on this machine by the way. You have done this with just 136 | user privileges to boot. 137 | 138 | PROBLEMS with Netcat 1.1 for NT 139 | 140 | There are a few known problems that will eventually be fixed. One is 141 | the -w or timeout option. This works for final net reads but not 142 | for connections. Another problem is using the -e option in UDP mode. 143 | You may find that some of the features work on Windows 95. Most 144 | of the listening features will not work on Windows 95 however. These will 145 | be fixed in a later release. 146 | 147 | Netcat is distributed with full source code so that people can build 148 | upon this work. If you add something useful or discover something 149 | interesting about NT TCP/IP let met know. 150 | 151 | Weld Pond , 2/2/98 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /testbinaries/switch/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int hoi; 5 | 6 | void a() 7 | { 8 | fprintf(stderr, "lol\n"); 9 | } 10 | 11 | void b() 12 | { 13 | hoi++; 14 | } 15 | 16 | void c() 17 | { 18 | fprintf(stderr, "hoi: %d\n", hoi); 19 | } 20 | 21 | int atoi(const char *a) 22 | { 23 | int ret = 0; 24 | while (*a) { 25 | ret = 10 * ret + *a++ - '0'; 26 | } 27 | return ret; 28 | } 29 | 30 | int Main() 31 | { 32 | int argc = 6; char *argv[] = {"0", "1", "2", "0", "1", "2"}; 33 | for (int i = 0; i < argc; i++) { 34 | switch (atoi(argv[i])) { 35 | case 0: a(); break; 36 | case 1: b(); break; 37 | case 2: c(); break; 38 | } 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /testbinaries/switch/switch.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {AE29F026-411B-4C4F-9617-FB38C0ACE701} 15 | switch 16 | 17 | 18 | 19 | Application 20 | true 21 | MultiByte 22 | 23 | 24 | Application 25 | false 26 | true 27 | MultiByte 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | false 41 | 42 | 43 | 44 | Level3 45 | Disabled 46 | 47 | 48 | true 49 | 50 | 51 | 52 | 53 | Level3 54 | Disabled 55 | true 56 | true 57 | false 58 | CompileAsCpp 59 | 60 | 61 | false 62 | true 63 | true 64 | "D:\Dropbox\CPP\msvcrt-compat\msvcrt.lib";"D:\Dropbox\CPP\msvcrt-compat\ntdll.lib";%(AdditionalDependencies) 65 | Console 66 | Main 67 | $(SolutionDir)..\$(TargetName)$(TargetExt) 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /testbinaries/switch/switch.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /testbinaries/switch/switch.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /tests.py: -------------------------------------------------------------------------------- 1 | import sys, enc, os, struct, subprocess, assemble 2 | from distorm3 import Registers, DecomposeGenerator, Decode32Bits 3 | from ctypes import * 4 | 5 | MEM_COMMIT = 0x1000 6 | MEM_RESERVE = 0x2000 7 | MEM_RELEASE = 0x8000 8 | PAGE_EXECUTE_READWRITE = 0x40 9 | 10 | ut = [] 11 | count = 0 12 | 13 | # unit test for register manipulation 14 | def ut_reg(hex, eax=0x11111111, ecx=0x22222222, edx=0x33333333, \ 15 | ebx=0x44444444, esp=0xb00b0ffc, ebp=0x66666666, esi=0x77777777, \ 16 | edi=0x88888888): 17 | ut.append({'type': 'reg', 'hex': hex, 'regs': (eax % 2**32, ecx % 2**32, \ 18 | edx % 2**32, ebx % 2**32, esp % 2**32, ebp % 2**32, esi % 2**32, \ 19 | edi % 2**32)}) 20 | 21 | # unit test for register manipulation *and* memory stuff 22 | def ut_mem(hex, eax=0x11111111, ecx=0x22222222, edx=0x33333333, \ 23 | ebx=0x44444444, esp=0xb00b0ffc, ebp=0x66666666, esi=0x77777777, \ 24 | edi=0x88888888, mem=[0,0,0,0]): 25 | if len(mem) != 4: mem = mem + [0 for i in xrange(4 - len(mem))] 26 | ut.append({'type': 'mem', 'hex': hex, 'regs': (eax % 2**32, ecx % 2**32, \ 27 | edx % 2**32, ebx % 2**32, esp % 2**32, ebp % 2**32, esi % 2**32, \ 28 | edi % 2**32), 'mem': mem[::-1]}) 29 | 30 | def test(debug): 31 | global count 32 | _stack = cdll.msvcrt.malloc(4 * 4) 33 | stack = _stack + 4 * 4 34 | code = windll.kernel32.VirtualAlloc(None, 0x1000, \ 35 | MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE) 36 | for test in ut: 37 | test['asm'] = [] ; enc.Enc(None).reset_labels() 38 | test['lines'] = [ 39 | 'jmp m128_init0_end', 40 | 'align 16, db 0', 41 | 'm128_init0: dd 0x11111111, 0x22222222, 0x33333333, 0x44444444', 42 | 'm128_init0_end:', 43 | 'jmp m128_init1_end', 44 | 'align 16, db 0', 45 | 'm128_init1: dd 0x%08x, 0x66666666, 0x77777777, 0x88888888' \ 46 | % stack, 'm128_init1_end:', 47 | 'movapd xmm6, dqword [m128_init0]', 48 | 'movapd xmm7, dqword [m128_init1]'] 49 | for dis in DecomposeGenerator(0, test['hex'].decode('hex'), \ 50 | Decode32Bits): 51 | test['lines'] += enc.Enc(dis).encode() 52 | test['asm'].append(str(dis)) 53 | test['code'] = assemble.assemble(test['lines'], 'testing/' + str(count)) 54 | 55 | sys.stderr.write('Processing %s -> %s (%d)\r' % \ 56 | (test['hex'], ' ; '.join(test['asm']), count)) 57 | output = list(struct.unpack('L' * 36, \ 58 | assemble.Debuggable(test['code'], _stack, code).run())) 59 | # adjust the `esp' register to remain correctly.. :) 60 | if (output[28] >> 16) == (stack >> 16): 61 | output[28] = 0xb00b0ffc - stack + output[28] 62 | if test['type'] in ['reg', 'mem'] and test['regs'] != \ 63 | tuple(output[24:32]): 64 | print '%s -> %s gave register problems (%d)!' % \ 65 | (test['hex'], ' ; '.join(test['asm']), count) 66 | print 'Generated SSE Assembly:\n' + '\n'.join(test['lines']) + '\n' 67 | # print all xmm registers 68 | for i in xrange(8): print 'xmm%d 0x%08x 0x%08x 0x%08x 0x%08x' % \ 69 | tuple([i] + list(output[i*4:i*4+4])) 70 | # print all gpr's stored in xmm registers, 71 | # 16 is offset of EAX in the Registers array 72 | for i in xrange(8): print '%s 0x%08x -> 0x%08x' % \ 73 | (Registers[16+i], output[24+i], test['regs'][i]) 74 | print '' # newline 75 | 76 | assemble.Debuggable(test['code'], _stack, code).debug() 77 | 78 | # unit test with memory changes 79 | elif test['type'] == 'mem' and test['mem'] != output[32:]: 80 | print '%s -> %s gave memory problems (%d)!' % \ 81 | (test['hex'], ' ; '.join(test['asm']), count) 82 | print 'Generated SSE Assembly:\n' + '\n'.join(test['lines']) + '\n' 83 | 84 | # print the memory stuff 85 | for i in xrange(len(output)-32): print '%-3d: 0x%08x -> 0x%08x' % \ 86 | (i, output[32+i], test['mem'][i]) 87 | print '' # newline 88 | 89 | assemble.Debuggable(test['code'], _stack, code).debug() 90 | 91 | elif debug: 92 | assemble.Debuggable(test['code'], _stack, code).debug() 93 | 94 | count += 1 95 | 96 | # free the stack 97 | cdll.msvcrt.free(_stack) 98 | 99 | # free the machine code 100 | windll.kernel32.VirtualFree(code, 0, MEM_RELEASE) 101 | 102 | def main(): 103 | index = None 104 | tests = ['mov', 'or', 'and', 'xor', 'add', 'inc', 'dec', 'xchg', 'push', \ 105 | 'pop', 'not', 'neg', 'leave', 'lea', 'shl', 'shr', 'mul', 'movzx'] 106 | if len(sys.argv) > 1: 107 | argc = 1 108 | try: 109 | index = int(sys.argv[argc]) 110 | argc += 1 111 | except: 112 | index = None 113 | 114 | if argc != len(sys.argv): 115 | tests = sys.argv[argc:] 116 | 117 | if not os.access('testing', os.R_OK): 118 | os.mkdir('testing') 119 | 120 | eax = 0x11111111 121 | ax = 0x1111 122 | al = 0x11 123 | ah = 0x11 124 | ecx = 0x22222222 125 | cx = 0x2222 126 | cl = 0x22 127 | ch = 0x22 128 | edx = 0x33333333 129 | dx = 0x3333 130 | dl = 0x33 131 | dh = 0x33 132 | ebx = 0x44444444 133 | bx = 0x4444 134 | bl = 0x44 135 | bh = 0x44 136 | # stack memory.. at address 0xb00b0000 with size = 0x1000 137 | esp = 0xb00b0ffc 138 | sp = 0xfffc 139 | ebp = 0x66666666 140 | bp = 0x6666 141 | esi = 0x77777777 142 | si = 0x7777 143 | edi = 0x88888888 144 | di = 0x8888 145 | 146 | if 'xor' in tests: 147 | # xor eax, eax 148 | ut_reg('33c0', eax=0) 149 | 150 | # xor edi, edi 151 | ut_reg('33ff', edi=0) 152 | 153 | # xor edx, 0x13371337 154 | ut_reg('81f237133713', edx=edx^0x13371337) 155 | 156 | # xor ebx, 0xdeadcafe 157 | ut_reg('81f3fecaadde', ebx=ebx^0xdeadcafe) 158 | 159 | # xor al, al 160 | ut_reg('32c0', eax=0x11111100) 161 | 162 | # xor ax, ax 163 | ut_reg('6633c0', eax=0x11110000) 164 | 165 | # xor ecx, 0xdeadf00d 166 | ut_reg('81f10df0adde', ecx=ecx^0xdeadf00d) 167 | 168 | # xor ecx, 3 169 | ut_reg('83f103', ecx=ecx^3) 170 | 171 | # xor ecx, 0x1337 172 | ut_reg('6681f13713', ecx=ecx^0x1337) 173 | 174 | # xor eax, ebx 175 | ut_reg('33c3', eax=eax^ebx) 176 | 177 | # xor edx, eax 178 | ut_reg('33d0', edx=edx^eax) 179 | 180 | # xor ecx, esi 181 | ut_reg('33ce', ecx=ecx^esi) 182 | 183 | if 'or' in tests: 184 | # or esi, 0xffff0000 185 | ut_reg('81ce0000ffff', esi=esi|0xffff0000) 186 | 187 | if 'and' in tests: 188 | # and ebx, 0x00ffff00 189 | ut_reg('81e300ffff00', ebx=ebx&0x00ffff00) 190 | 191 | if 'mov' in tests: 192 | # mov ebx, edx 193 | ut_reg('8bda', ebx=edx) 194 | 195 | # mov esi, ebx 196 | ut_reg('8bf3', esi=ebx) 197 | 198 | # mov ecx, 0xdeadf00d 199 | ut_reg('b90df0adde', ecx=0xdeadf00d) 200 | 201 | # mov cx, 0xd00d 202 | ut_reg('66b90dd0', ecx=0x2222d00d) 203 | 204 | # mov cl, 0x42 205 | ut_reg('b142', ecx=0x22222242) 206 | 207 | # mov cx, si 208 | ut_reg('668bce', ecx=0x7777) 209 | 210 | # mov esp, ebp 211 | ut_reg('8be5', esp=ebp) 212 | 213 | # push 0 ; mov dword [esp], 0x87654321 214 | ut_mem('6a00c7042421436587', mem=[0x87654321], esp=esp-4) 215 | 216 | if 'add' in tests: 217 | # add ecx, esi 218 | ut_reg('03ce', ecx=ecx+esi) 219 | 220 | # add ebx, 0xcafebabe 221 | ut_reg('81c3bebafeca', ebx=ebx+0xcafebabe) 222 | 223 | if 'inc' in tests: 224 | # inc eax 225 | ut_reg('40', eax=eax+1) 226 | 227 | # inc esi 228 | ut_reg('46', esi=esi+1) 229 | 230 | if 'dec' in tests: 231 | # dec eax 232 | ut_reg('48', eax=eax-1) 233 | 234 | # dec esi 235 | ut_reg('4e', esi=esi-1) 236 | 237 | if 'xchg' in tests: 238 | # xchg ebx, ecx 239 | ut_reg('87cb', ebx=ecx, ecx=ebx) 240 | 241 | # xchg edx, edi 242 | ut_reg('87fa', edx=edi, edi=edx) 243 | 244 | if 'push' in tests or 'pop' in tests: 245 | # push 0x13371337 246 | ut_mem('6837133713', esp=esp-4, mem=[0x13371337]) 247 | 248 | # push 0xdeadf00d ; pop edx 249 | ut_mem('680df0adde5a', mem=[0xdeadf00d], edx=0xdeadf00d) 250 | 251 | # push 0xabcddcba ; push 0xdefdefde 252 | ut_mem('68badccdab68deeffdde', mem=[0xabcddcba, 0xdefdefde], esp=esp-8) 253 | 254 | if 'not' in tests: 255 | # not eax 256 | ut_reg('f7d0', eax=~eax) 257 | 258 | # not eax ; not eax 259 | ut_reg('f7d0' * 2) 260 | 261 | if 'neg' in tests: 262 | # neg eax 263 | ut_reg('f7d8', eax=-eax) 264 | 265 | # xor eax, eax ; dec eax ; neg eax 266 | ut_reg('33c048f7d8', eax=1) 267 | 268 | if 'leave' in tests: 269 | # push 0x12345678 ; mov ebp, esp ; leave 270 | ut_mem('68785634128becc9', mem=[0x12345678], ebp=0x12345678) 271 | 272 | # this crashes python, so this can only be executed 273 | # by explicitely defining `ret' on the commandline 274 | if 'ret' in tests: 275 | # push 0x41414141 ; retn 276 | ut_mem('6841414141c3') 277 | 278 | if 'lea' in tests: 279 | # lea eax, [eax+ebx*4+0xb00b] 280 | ut_reg('8d84980bb00000', eax=0x2222d22c) 281 | 282 | # lea ecx, [esi+edx] 283 | ut_reg('8d0c32', ecx=0xaaaaaaaa) 284 | 285 | if 'shl' in tests: 286 | # shl eax, 2 287 | ut_reg('c1e002', eax=0x44444444) 288 | 289 | # mov ecx, 4 ; shl esi, cl 290 | ut_reg('b904000000d3e6', esi=0x77777770, ecx=4) 291 | 292 | if 'shr' in tests: 293 | # shr ecx, 3 294 | ut_reg('c1e903', ecx=0x04444444) 295 | 296 | # mov ecx, 9 ; shr ebp, cl 297 | ut_reg('b909000000d3ed', ecx=9, ebp=0x00333333) 298 | 299 | if 'mul' in tests: 300 | # mul ebx 301 | ut_reg('f7e3', eax=0x1d950c84, edx=0x048d159e) 302 | 303 | if 'movzx' in tests: 304 | # movzx eax, dl 305 | ut_reg('0fb6c2', eax=0x00000033) 306 | 307 | # movzx eax, dx 308 | ut_reg('0fb7c2', eax=0x00003333) 309 | 310 | # push 0x1337b00b ; movzx esi, word [esp] 311 | ut_mem('680bb037130fb73424', mem=[0x1337b00b], esi=0xb00b, esp=esp-4) 312 | 313 | # only do a certain test 314 | debug = False 315 | if index is not None: 316 | global ut 317 | ut = [ut[index]] 318 | debug = True 319 | 320 | test(debug) 321 | 322 | if __name__ == '__main__': 323 | main() -------------------------------------------------------------------------------- /translate.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Translates the x86 General Purpose Instructions into SSE Instructions. 4 | 5 | Unfortunately the current implementations only allows 1:1 translation, newer 6 | versions should support translation of multiple instructions at once. 7 | 8 | xmm0 = input 9 | xmm1 = output 10 | xmm2 = intermediate (used in handlers that also call `core' apis) 11 | xmm3 = temporary (used in `core' apis) 12 | 13 | """ 14 | import sys 15 | 16 | # one of the main reasons translation is done in a seperate module 17 | from pyasm2.x86 import * 18 | 19 | def translate(instr): 20 | """TranslateCeption?""" 21 | return Translator(instr).translate() 22 | 23 | class Translater: 24 | def __init__(self, instr, m128s, m32s): 25 | self.instr = instr 26 | self.m128s = m128s 27 | self.m32s = m32s 28 | self.block = block() 29 | self._reg_index = 0 30 | 31 | def m128(self, *val): 32 | """Creates a m128 and returns its label.""" 33 | length = len(self.m128s) 34 | semi_addr = 0xff000000 + length 35 | self.m128s.append(('__lbl_%08x: ' + '.long %s ; ' * 4) % 36 | tuple([semi_addr] + map(str, val))) 37 | return MemoryAddress(size=128, 38 | disp=Immediate(value=semi_addr, addr=True)) 39 | 40 | def m32(self, value): 41 | """Creates a m32 and returns its label.""" 42 | length = len(self.m32s) 43 | semi_addr = 0xfe000000 + length 44 | value = value if value is not None else 0 45 | self.m32s.append('__lbl_%08x: .long %s' % (semi_addr, str(value))) 46 | return MemoryAddress(size=32, 47 | disp=Immediate(value=semi_addr, addr=True)) 48 | 49 | def m128_field(self, field, value, other=0): 50 | """Returns an m128 with `value' in `field', other field become 0.""" 51 | assert field in xrange(4) 52 | 53 | args = (value if x == field else other for x in xrange(4)) 54 | return self.m128(*args) 55 | 56 | def usable_gpr(self): 57 | """In order to load xmm registers, GPRs are needed, but which one?""" 58 | # simply iterate through them all. 59 | ret = gpr.register32[self._reg_index % 8] 60 | self._reg_index += 1 61 | return ret 62 | 63 | def mem_eval(self, dst, src): 64 | """Evaluate a Memory Address `src' into XMM Register `dst'.""" 65 | assert isinstance(src, mem) 66 | assert isinstance(dst, xmm) 67 | 68 | # if `src' is a memory address of which `reg1' *or* `reg2' is set, 69 | # then we have to evaluate this memory address 70 | if src.reg1 or src.reg2: 71 | # load the displacement 72 | self.block += movd(xmm3, self.m32(src.disp)) 73 | 74 | # if `reg1' is set, add it 75 | if src.reg1: 76 | self.read_gpr(xmm2, src.reg1) 77 | self.block += paddd(xmm3, xmm2) 78 | 79 | # if `reg2' is set, add it 80 | if src.reg2: 81 | self.read_gpr(xmm2, src.reg2) 82 | self.block += pslld(xmm2, {1: 0, 2: 1, 4: 2, 8: 3}[src.mult]) 83 | self.block += paddd(xmm3, xmm2) 84 | 85 | # store the value into `dst' 86 | self.block += movups(dst, xmm3) 87 | else: 88 | # there is only a displacement 89 | self.block += movd(dst, self.m32(src.disp)) 90 | 91 | def xmm_load(self, dst, src): 92 | """Load xmm register `dst' with anything inside `src'.""" 93 | assert dst.size == 128 94 | 95 | if isinstance(src, mem): 96 | self.mem_eval(xmm3, src) 97 | gpr1 = self.usable_gpr() 98 | self.block += movd(gpr1, xmm3) 99 | f = mov if src.size == 32 else movzx 100 | g = {8: byte, 16: word, 32: dword}[src.size] 101 | self.block += f(gpr1, g[gpr1]) 102 | self.block += movd(xmm3, gpr1) 103 | src = xmm3 104 | 105 | if isinstance(src, imm): 106 | self.block += movd(xmm3, self.m32(src)) 107 | src = xmm3 108 | 109 | #sys.stderr.write('dst: %s, src: %s\n' % (dst, src)) 110 | 111 | # now read the value. 112 | if src.size == 128: 113 | self.block += movups(dst, src) 114 | elif src.size == 32: 115 | gpr = self.usable_gpr() 116 | self.block += mov(gpr, src) 117 | self.block += movd(dst, gpr) 118 | else: 119 | gpr = self.usable_gpr() 120 | self.block += movzx(gpr, src) 121 | self.block += movd(dst, gpr) 122 | 123 | def memory_write(self, dst, src): 124 | """Write `src' to `dst'.""" 125 | # resolve the address in `dst' 126 | assert isinstance(dst, mem) 127 | 128 | self.mem_eval(xmm3, dst) 129 | gpr1 = self.usable_gpr() 130 | self.block += movd(gpr1, xmm3) 131 | dst = mem(size=dst.size, reg1=gpr1) 132 | 133 | #sys.stderr.write('dst: %s, src: %s, gpr1: %s\n' % (dst, src, gpr1)) 134 | 135 | if isinstance(src, gpr): 136 | self.read_gpr(xmm0, src) 137 | src = xmm0 138 | elif isinstance(src, mem): 139 | self.xmm_load(xmm0, src) 140 | src = xmm0 141 | 142 | # register to an address or similar 143 | if dst.size in (8, 16, 32) and (dst.size == src.size or 144 | isinstance(src, imm)): 145 | #sys.stderr.write('dst: %s, src: %s\n' % (dst, src)) 146 | self.block += mov(dst, src) 147 | 148 | # from an xmm register to an address 149 | elif dst.size in (8, 16, 32) and src.size == 128: 150 | gpr2 = self.usable_gpr() 151 | self.block += movd(gpr2, src) 152 | #sys.stderr.write('dst: %s, gpr2: %s\n' % (dst, gpr2)) 153 | self.block += mov(dst, gpr.registers[dst.size][gpr2.index]) 154 | 155 | else: 156 | raise Exception('dst: %d, src: %d' % (dst.size, src.size)) 157 | 158 | def read_gpr(self, dst, src): 159 | """Read a General Purpose Register into `dst'.""" 160 | assert isinstance(src, gpr) 161 | 162 | reg = xmm6 if src.index < 4 else xmm7 163 | if isinstance(dst, xmm): 164 | self.block += pshufd(dst, reg, src.index & 3) 165 | 166 | elif isinstance(dst, gpr): 167 | self.block += pshufd(xmm3, reg, src.index & 3) 168 | self.block += movd(dst, xmm3) 169 | 170 | else: 171 | assert isinstance(dst, mem) 172 | 173 | # evaluate the address in `dst' 174 | self.mem_eval(xmm2, dst) 175 | gpr1 = self.usable_gpr() 176 | self.block += movd(gpr, xmm2) 177 | dst = mem(size=dst.size, reg1=gpr1) 178 | 179 | # read the gpr 180 | self.block += pshufd(xmm3, reg, src.index & 3) 181 | 182 | f = mov if dst.size == 32 else movzx 183 | 184 | # write the gpr to `dst' 185 | gpr2 = self.usable_gpr() 186 | self.block += movd(gpr2, xmm3) 187 | self.block += f(dst, gpr2) 188 | 189 | def write_gpr(self, dst, src): 190 | """Write `src' to a General Purpose Register `dst'.""" 191 | assert isinstance(dst, gpr) 192 | 193 | if isinstance(src, mem): 194 | self.mem_eval(xmm3, src) 195 | # 32bit support only atm 196 | gpr1 = self.usable_gpr() 197 | self.block += movd(gpr1, xmm3) 198 | self.block += movd(xmm3, dword[gpr1]) 199 | src = xmm3 200 | elif isinstance(src, gpr): 201 | # TODO 8/16bit 202 | self.block += movd(xmm3, src) 203 | src = xmm3 204 | elif isinstance(src, imm): 205 | self.block += movd(xmm3, self.m32(src)) 206 | 207 | if isinstance(src, xmm): 208 | reg = xmm6 if dst.index < 4 else xmm7 209 | self.block += pshufd(src, src, 0) 210 | self.block += pand(src, self.m128_field(dst.index & 3, -1)) 211 | self.block += pand(reg, self.m128_field(dst.index & 3, 0, -1)) 212 | self.block += pxor(reg, src) 213 | else: 214 | raise Exception('wut?') 215 | 216 | def add_gpr(self, dst, val): 217 | """Add `val' to General Purpose Register `dst'.""" 218 | self.read_gpr(xmm3, dst) 219 | self.block += paddd(xmm3, self.m128(val, 0, 0, 0)) 220 | self.write_gpr(dst, xmm3) 221 | 222 | def sub_gpr(self, dst, val): 223 | """Subtract `val' from General Purpose Register `dst'.""" 224 | self.read_gpr(xmm3, dst) 225 | self.block += psubd(xmm3, self.m128(val, 0, 0, 0)) 226 | self.write_gpr(dst, xmm3) 227 | 228 | def read_operand(self, dst, src): 229 | """Read value at operand `src' into XMM Register `dst'.""" 230 | if isinstance(src, gpr): 231 | self.read_gpr(dst, src) 232 | else: 233 | assert isinstance(src, (imm, mem)) 234 | 235 | self.xmm_load(dst, src) 236 | 237 | def write_operand(self, dst, src): 238 | """Write value `src' into anything specified by operand `dst'.""" 239 | if isinstance(dst, gpr): 240 | self.write_gpr(dst, src) 241 | else: 242 | assert isinstance(dst, mem) 243 | 244 | self.memory_write(dst, src) 245 | 246 | def translate(self): 247 | #sys.stderr.write('instr: %s\n' % str(self.instr)) 248 | f = getattr(self, 'encode_' + self.instr.mnemonic(), None) 249 | if not f: 250 | sys.stderr.write('Cannot encode %s\n' % self.instr.mnemonic()) 251 | return block(self.instr) 252 | 253 | f() 254 | return self.block 255 | 256 | def t(self, *instructions): 257 | """Translate a sequence of instructions.""" 258 | for x in instructions: 259 | self.instr = x 260 | self.translate() 261 | 262 | def encode_push(self): 263 | self.sub_gpr(esp, 4) 264 | self.memory_write(dword[esp], self.instr.op1) 265 | 266 | def encode_mov(self): 267 | self.read_operand(xmm0, self.instr.op2) 268 | self.write_operand(self.instr.op1, xmm0) 269 | 270 | def encode_call(self): 271 | # if a third party api is called, and `resets' is set to True, then 272 | # we have to store the xmm6 and xmm7 registers temporarily. As `esp' 273 | # is altered by the function call, we store this in `ebp'. 274 | 275 | #sys.stderr.write( 276 | 277 | if isinstance(self.instr, RelativeJump): 278 | # push the return address on the stack 279 | self.sub_gpr(esp, 4) 280 | # again, _terrible_ 281 | self.memory_write(dword[esp], imm(addr=True, 282 | value=int(str(self.instr.lbl)[6:], 16) + 0xfc000000)) 283 | self.block.instructions[-1].op2 = 'offset flat:' + \ 284 | str(self.block.instructions[-1].op2) 285 | self.instr._name_ = 'jmp' 286 | 287 | # prepare `esp', the stack pointer 288 | self.read_gpr(esp, esp) 289 | 290 | self.block += self.instr 291 | 292 | if isinstance(self.instr, RelativeJump): 293 | self.block += Label( 294 | str('%08x' % (int(str(self.instr.lbl)[6:], 16) + 0xfc000000))) 295 | self.add_gpr(esp, 4) 296 | 297 | # store the result stored in `eax' 298 | self.write_gpr(eax, eax) 299 | 300 | def encode_retn(self): 301 | self.read_gpr(eax, eax) 302 | self.add_gpr(esp, 4) 303 | self.read_gpr(esp, esp) 304 | self.block += jmp(dword[esp-4]) 305 | 306 | def encode_add(self): 307 | self.read_operand(xmm0, self.instr.op1) 308 | self.read_operand(xmm1, self.instr.op2) 309 | self.block += paddd(xmm0, xmm1) 310 | self.write_operand(self.instr.op1, xmm0) 311 | 312 | def encode_pop(self): 313 | self.write_operand(self.instr.op1, dword[esp]) 314 | self.add_gpr(esp, 4) 315 | 316 | def encode_xor(self): 317 | self.read_operand(xmm0, self.instr.op1) 318 | self.read_operand(xmm1, self.instr.op2) 319 | self.block += pxor(xmm0, xmm1) 320 | self.write_operand(self.instr.op1, xmm0) 321 | 322 | def encode_sub(self): 323 | self.read_operand(xmm0, self.instr.op1) 324 | self.read_operand(xmm1, self.instr.op2) 325 | self.block += psubd(xmm0, xmm1) 326 | self.write_operand(self.instr.op1, xmm0) 327 | 328 | def encode_test(self): 329 | # assume two gpr's are used 330 | self.read_gpr(eax, self.instr.op1) 331 | self.read_gpr(ebx, self.instr.op2) 332 | self.block += test(eax, ebx) 333 | 334 | def encode_lea(self): 335 | self.mem_eval(xmm0, self.instr.op2) 336 | self.write_gpr(self.instr.op1, xmm0) 337 | 338 | def encode_cmp(self): 339 | self.read_operand(xmm0, self.instr.op1) 340 | self.read_operand(xmm1, self.instr.op2) 341 | self.block += movd(eax, xmm0) 342 | self.block += movd(ebx, xmm1) 343 | self.block += cmp(eax, ebx) 344 | 345 | def encode_imul(self): 346 | self.read_operand(xmm0, self.instr.op1) 347 | self.read_operand(xmm1, self.instr.op2) 348 | self.block += pmuludq(xmm0, xmm1) 349 | self.write_gpr(self.instr.op1, xmm0) 350 | 351 | def encode_movzx(self): 352 | self.read_operand(xmm0, self.instr.op2) 353 | flag = 0xff if self.instr.op1.size == 8 else 0xffff 354 | self.block += pand(xmm0, self.m128(flag, 0, 0, 0)) 355 | self.write_gpr(self.instr.op1, xmm0) 356 | 357 | def encode_div(self): 358 | self.read_gpr(xmm0, eax) 359 | self.read_operand(xmm1, self.instr.op1) 360 | self.block += cvtdq2pd(xmm0, xmm0) 361 | self.block += cvtdq2pd(xmm1, xmm1) 362 | self.block += movups(xmm2, xmm0) 363 | self.block += divpd(xmm0, xmm1) # xmm0 = eax / op1 364 | self.block += subpd(xmm2, xmm1) # xmm2 = eax - eax / op1 = eax % op1 365 | self.block += cvttpd2dq(xmm0, xmm0) 366 | self.block += cvttpd2dq(xmm2, xmm2) 367 | self.write_gpr(eax, xmm0) 368 | self.write_gpr(edx, xmm2) 369 | 370 | def encode_and(self): 371 | self.read_gpr(xmm0, self.instr.op1) 372 | self.read_operand(xmm1, self.instr.op2) 373 | self.block += pand(xmm0, xmm1) 374 | self.write_gpr(self.instr.op1, xmm0) 375 | 376 | def encode_leave(self): 377 | x = self.instr 378 | self.t(mov(esp, ebp), pop(ebp)) 379 | self.instr = x 380 | --------------------------------------------------------------------------------