blob: 90d6c8e568033ee36b15ded957e8b605568d4b38 [file] [log] [blame]
/* **********************************************************
* Copyright (c) 2005-2007 VMware, Inc. All rights reserved.
* **********************************************************/
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of VMware, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#include <stdio.h>
#include "share.h"
#include "utils.h"
#include "hotp-test.h"
#define OUTFILE L"tester.out"
#define ATTACK_NONE 0
#define ATTACK_STACK 1
#define ATTACK_HEAP 2
int attack_status = ATTACK_NONE;
DWORD
WINAPI
heap_attack(LPVOID param);
DWORD
WINAPI
stack_attack(LPVOID param);
DWORD
WINAPI
ls_attack(LPVOID param);
enum { stack=1, heap, liveshield };
/* disable type case warning for attacks below. */
#pragma warning(disable : 4055)
void usage() {
fprintf(stderr,
" usage: tester [initial_sleep_ms] [attack] [num_attacks]\n"
"\n"
" tester will then do:\n"
" (1) [initial_sleep_ms] sleep before doing anything\n"
" (2) if [attack]/[num_attacks] params are not set, exits\n"
" (3) [attack=1,2 or 3] (executes 1=stack, 2=heap or 3=liveshield attack \n"
" (1) liveshield attacks execute test_reg and test_control_flow hotpatches\n"
" (equivalent of araktest liveshield buttons 1 and 2)\n"
" (2) write to \"tester.out.xx\" two characters:\n"
" -- 0 or 1 according to whether test_reg was patched\n"
" -- 0 or 1 according to whether test_control_flow was patched\n"
" (4) repeat step (3) [num_attacks] times\n"
"\n"
" To run under DR setup appropriate registry settings for tester.exe\n");
}
int
main(int argc, char **argv)
{
int timeout = 5000;
/*char output[MAX_PATH];*/
if (argc == 2
&& (_stricmp(argv[1], "-h") == 0 || _stricmp(argv[1], "-help") == 0)) {
usage();
exit(0);
}
if (argc >= 2)
timeout = atoi(argv[1]);
Sleep(timeout);
if (argc >= 3) {
int i, count = 1;
int attack = atoi(argv[2]);
if (attack == 0) {
fprintf(stderr, "attack=%d not expected\n", attack);
usage();
exit (-1);
}
if (argc >= 4)
count = atoi(argv[3]);
for (i = 0; i < count; i++) {
HANDLE athr;
fprintf(stderr, "loop %d\n",i);
if (attack == 1)
athr= CreateThread(NULL, 0, stack_attack, NULL, 0, NULL);
else if (attack == 2)
athr= CreateThread(NULL, 0, heap_attack, NULL, 0, NULL);
else if (attack == 3)
athr= CreateThread(NULL, 0, ls_attack, (void*)i, 0, NULL);
else {
fprintf(stderr, "attack=%d can take 1,2 or 3\n", attack);
usage();
exit(-1);
}
if (athr == NULL) {
fprintf(stderr, "tc %d\n", GetLastError());
exit (-1);
}
WaitForSingleObject(athr, INFINITE);
CloseHandle(athr);
}
}
return 0;
}
/*
123:
124: void test(void(*f)(int), int i)
125:
126: {
004012A0 55 push ebp
004012A1 8B EC mov ebp,esp
004012A3 83 EC 40 sub esp,40h
004012A6 53 push ebx
004012A7 56 push esi
004012A8 57 push edi
004012A9 8D 7D C0 lea edi,[ebp-40h]
004012AC B9 10 00 00 00 mov ecx,10h
004012B1 B8 CC CC CC CC mov eax,0CCCCCCCCh
004012B6 F3 AB rep stos dword ptr [edi] ****GET RID OF THIS CRAP ****
127: (f)(i);
004012B8 8B F4 mov esi,esp
004012BA 8B 45 0C mov eax,dword ptr [ebp+0Ch]
004012BD 50 push eax
004012BE FF 55 08 call dword ptr [ebp+8]
004012C1 83 C4 04 add esp,4
004012C4 3B F4 cmp esi,esp
004012C6 E8 55 10 00 00 call _chkesp (00402320) ***GET RID OF THIS B'COZ ABS ADDR ****
128: return;
129: }
004012CB 5F pop edi
004012CC 5E pop esi
004012CD 5B pop ebx
004012CE 83 C4 40 add esp,40h
004012D1 3B EC cmp ebp,esp
004012D3 E8 48 10 00 00 call _chkesp (00402320) ***GET RID OF THIS B'COZ ABS ADDR ****
004012D8 8B E5 mov esp,ebp
004012DA 5D pop ebp
004012DB C3 ret
*/
unsigned char test_compiled_with_debug[] = {
0x55,
0x8B, 0xEC,
0x83, 0xEC, 0x40,
0x53,
0x56,
0x57,
0x8D, 0x7D, 0xC0,
0xB9, 0x10, 0x00, 0x00, 0x00,
0xB8, 0xCC, 0xCC, 0xCC, 0xCC,
/* 0xF3, 0xAB, */
0x8B, 0xF4,
0x8B, 0x45, 0x0C,
0x50,
0xFF, 0x55, 0x08,
0x83, 0xC4, 0x04,
0x3B, 0xF4,
/* 0xE8, 0xC5, 0x0E, 0x00, 0x00, */
0x5F,
0x5E,
0x5B,
0x83, 0xC4, 0x40,
0x3B, 0xEC,
/* 0xE8, 0xB8, 0x0E, 0x00, 0x00, */
0x8B, 0xE5,
0x5D,
0xC3,
0x00, 0x00, 0x00, 0x00 };
void test(void(*f)(int), int i)
{
(f)(i);
return;
}
/*
123:
124: void test(void(*f)(int), int i)
125:
126: {
004012A0 55 push ebp
004012A1 8B EC mov ebp,esp
127: (f)(i);
004012BA 8B 45 0C mov eax,dword ptr [ebp+0Ch]
004012BD 50 push eax
004012BE FF 55 08 call dword ptr [ebp+8]
128: return;
129: }
004012D8 8B E5 mov esp,ebp
004012DA 5D pop ebp
004012DB C3 ret
*/
unsigned char sendfunc[] = {
0x55,
0x8B, 0xEC,
0x8B, 0x45, 0x0C,
0x50,
0xFF, 0x55, 0x08,
0x8B, 0xE5,
0x5D,
0xC3,
0x00, 0x00, 0x00, 0x00 };
void set_attack(int i)
{
attack_status = i;
}
void fool_opt_compiler(unsigned char * foo)
{
foo[0] =1;
}
DWORD
WINAPI
stack_attack(LPVOID param)
{
unsigned char myfunc[1024];
int i;
/* use the param to make compiler happy */
if (param == NULL)
i = 0;
if(sizeof(sendfunc)>=sizeof(myfunc))
MessageBox(NULL, L"ERROR", L"Memory allocation problem", MB_OK);
for(i=0; i<sizeof(sendfunc); i++)
myfunc[i] = sendfunc[i];
((void(*)(void(*)(int),int))((void *)myfunc))(set_attack, ATTACK_STACK);
fool_opt_compiler(myfunc);
return ERROR_SUCCESS;
}
DWORD
WINAPI
heap_attack(LPVOID param)
{
unsigned char * myfunc;
int i;
/* use the param to make compiler happy */
if (param == NULL)
i = 0;
myfunc = (unsigned char *) malloc(sizeof(sendfunc));
if(myfunc == NULL)
MessageBox(NULL, L"ERROR", L"Memory allocation problem", MB_OK);
for(i=0; i<sizeof(sendfunc); i++)
myfunc[i] = sendfunc[i];
((void(*)(void(*)(int),int))((void *)myfunc))(set_attack, ATTACK_HEAP);
free(myfunc);
return ERROR_SUCCESS;
}
DWORD
WINAPI
ls_attack(LPVOID param)
{
char output[MAX_PATH];
WCHAR filename[MAX_PATH];
_snwprintf(filename, MAX_PATH, L"%s.%d", OUTFILE, (int)param);
delete_file_rename_in_use(filename);
_snprintf(output, MAX_PATH,
"%d%d\n", hotp_test_reg(), hotp_test_control_flow());
write_file_contents(filename, output, TRUE);
return ERROR_SUCCESS;
}