Skip to content

Commit

Permalink
Merge branch 'faster' (Issue #17)
Browse files Browse the repository at this point in the history
  • Loading branch information
hasherezade committed Jan 19, 2022
2 parents 30a93cb + ad9653c commit b07b7e9
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 22 deletions.
54 changes: 32 additions & 22 deletions TinyTracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include "FuncWatch.h"

#define TOOL_NAME "TinyTracer"
#define VERSION "2.0"
#define VERSION "2.0-a"

#include "Util.h"
#include "Settings.h"
Expand Down Expand Up @@ -146,22 +146,28 @@ bool isWatchedAddress(const ADDRINT Address)
// Analysis routines
/* ===================================================================== */


VOID _SaveTransitions(const ADDRINT addrFrom, const ADDRINT addrTo, BOOL isIndirect, ADDRINT returnAddr = UNKNOWN_ADDR)
ADDRINT getReturnFromTheStack(const CONTEXT* ctx)
{
// validate the return address:
if (returnAddr != UNKNOWN_ADDR && !PIN_CheckReadAccess((void*)returnAddr)) {
returnAddr = UNKNOWN_ADDR;
if (!ctx) return UNKNOWN_ADDR;

ADDRINT returnAddr = UNKNOWN_ADDR;
const ADDRINT stackPtr = (ADDRINT)PIN_GetContextReg(ctx, REG_STACK_PTR);
if (PIN_CheckReadAccess((ADDRINT*)stackPtr)) {
returnAddr = *(ADDRINT*)stackPtr;
}
return returnAddr;
}

VOID _SaveTransitions(const ADDRINT addrFrom, const ADDRINT addrTo, BOOL isIndirect, const CONTEXT* ctx = NULL)
{
const bool isTargetMy = pInfo.isMyAddress(addrTo);
const bool isCallerMy = pInfo.isMyAddress(addrFrom);


bool isFromTraced = isWatchedAddress(addrFrom); // is the call from the traced shellcode?
bool isRetToTraced = isWatchedAddress(returnAddr); // does it return into the traced area?

IMG targetModule = IMG_FindByAddress(addrTo);
IMG callerModule = IMG_FindByAddress(addrFrom);
const bool isCallerPeModule = IMG_Valid(callerModule);
const bool isTargetPeModule = IMG_Valid(targetModule);

/**
Expand All @@ -185,7 +191,7 @@ VOID _SaveTransitions(const ADDRINT addrFrom, const ADDRINT addrTo, BOOL isIndir
/**
trace calls from witin a shellcode:
*/
if (m_Settings.followShellcode && !IMG_Valid(callerModule)) {
if (m_Settings.followShellcode && !isCallerPeModule) {

if (m_Settings.followShellcode == SHELLC_FOLLOW_ANY || isFromTraced) {
const ADDRINT pageFrom = query_region_base(addrFrom);
Expand Down Expand Up @@ -219,20 +225,24 @@ VOID _SaveTransitions(const ADDRINT addrFrom, const ADDRINT addrTo, BOOL isIndir
/**
save the transition when a shellcode returns to a traced area from an API call:
*/
if (isRetToTraced //returns to the traced area
&& !isFromTraced && !IMG_Valid(callerModule) // from an untraced shellcode...
&& isTargetPeModule // ...which was was a proxy for making an API call
if (!isFromTraced && !isCallerPeModule // from an untraced shellcode...
&& isTargetPeModule // ...into an API call
&& ctx //the context was passed: we can check the return
)
{
const std::string func = get_func_at(addrTo);
const std::string dll_name = IMG_Name(targetModule);
const ADDRINT pageRet = get_base(returnAddr);
const ADDRINT RvaFrom = addr_to_rva(addrFrom);
const ADDRINT base = isTargetMy ? 0 : get_base(addrFrom);
// was the shellcode a proxy for making an API call?
const ADDRINT returnAddr = getReturnFromTheStack(ctx);
bool isRetToTraced = isWatchedAddress(returnAddr); // does it return into the traced area?
if (isRetToTraced) {
const std::string func = get_func_at(addrTo);
const std::string dll_name = IMG_Name(targetModule);
const ADDRINT pageRet = get_base(returnAddr);
const ADDRINT RvaFrom = addr_to_rva(addrFrom);
const ADDRINT base = isTargetMy ? 0 : get_base(addrFrom);

traceLog.logCallRet(base, RvaFrom, pageRet, returnAddr, dll_name, func);
traceLog.logCallRet(base, RvaFrom, pageRet, returnAddr, dll_name, func);
}
}

/**
trace indirect calls to your own functions
*/
Expand Down Expand Up @@ -269,10 +279,10 @@ VOID _SaveTransitions(const ADDRINT addrFrom, const ADDRINT addrTo, BOOL isIndir
}
}

VOID SaveTransitions(const ADDRINT prevVA, const ADDRINT Address, BOOL isIndirect, const ADDRINT RetAddress)
VOID SaveTransitions(const ADDRINT prevVA, const ADDRINT Address, BOOL isIndirect, const CONTEXT* ctx)
{
PinLocker locker;
_SaveTransitions(prevVA, Address, isIndirect, RetAddress);
_SaveTransitions(prevVA, Address, isIndirect, ctx);
}

VOID RdtscCalled(const CONTEXT* ctxt)
Expand Down Expand Up @@ -531,7 +541,7 @@ VOID InstrumentInstruction(INS ins, VOID *v)
IARG_INST_PTR,
IARG_BRANCH_TARGET_ADDR,
IARG_BOOL, isIndirect,
IARG_RETURN_IP,
IARG_CONTEXT,
IARG_END
);

Expand Down
135 changes: 135 additions & 0 deletions install32_64/run_me_benchmark.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
@echo off
rem This script is to be used from the context menu

set TARGET_APP=%~1
set PE_TYPE=%~2
set IS_ADMIN=%~3

if "%TARGET_APP%"=="" goto display_args
if "%PE_TYPE%"=="" goto display_args
goto run_it

:display_args
echo Run a process with TinyTracer, and trace the selected module
echo It is recommended to run this script via installed context menu
echo Required args: [target app] [pe type: dll or exe]
pause
goto finish

:run_it
echo PIN is trying to run the app:
echo "%TARGET_APP%"

rem PIN_DIR is your root directory of Intel Pin
set PIN_DIR=C:\pin\

rem PIN_TOOLS_DIR is your directory with this script and the Pin Tools
set PIN_TOOLS_DIR=C:\pin\source\tools\tiny_tracer\install32_64\

set PINTOOL32=%PIN_TOOLS_DIR%\TinyTracer32.dll
set PINTOOL64=%PIN_TOOLS_DIR%\TinyTracer64.dll
set PINTOOL=%PINTOOL32%

rem TRACED_MODULE - by default it is the main module, but it can be also a DLL within the traced process
set TRACED_MODULE=%TARGET_APP%

set TAG_FILE="%TRACED_MODULE%.tag"

rem The ini file specifying the settings of the tracer
set SETTINGS_FILE=%PIN_TOOLS_DIR%\TinyTracer.ini

rem WATCH_BEFORE - a file with a list of functions which's parameters will be logged before execution
rem The file must be a list of records in a format: [dll_name];[func_name];[parameters_count]
set WATCH_BEFORE=%PIN_TOOLS_DIR%\params.txt

set DLL_LOAD32=%PIN_TOOLS_DIR%\dll_load32.exe
set DLL_LOAD64=%PIN_TOOLS_DIR%\dll_load64.exe

if exist %PIN_TOOLS_DIR%\kdb_check.exe (
%PIN_TOOLS_DIR%\kdb_check.exe
if NOT %errorlevel% EQU 0 (
echo Disable Kernel Mode Debugger before running the PIN tool!
pause
exit
)
)

%PIN_TOOLS_DIR%\pe_check.exe "%TARGET_APP%"
if %errorlevel% == 32 (
echo 32bit selected
set PINTOOL=%PINTOOL32%
set DLL_LOAD=%DLL_LOAD32%
)
if %errorlevel% == 64 (
echo 64bit selected
set PINTOOL=%PINTOOL64%
set DLL_LOAD=%DLL_LOAD64%
)

rem The exports that you want to call from a dll, in format: [name1];[name2] or [#ordinal1];[#ordinal2]
set DLL_EXPORTS=""

rem The arguments that you want to pass to the run executable
set EXE_ARGS=""

echo Target module: "%TRACED_MODULE%"
echo Tag file: %TAG_FILE%
if [%IS_ADMIN%] == [A] (
echo Elevation requested
)

set ADMIN_CMD=%PIN_TOOLS_DIR%\sudo.vbs

set DLL_CMD=%PIN_DIR%\pin.exe -t %PINTOOL% -m "%TRACED_MODULE%" -o %TAG_FILE% -s %SETTINGS_FILE% -b "%WATCH_BEFORE%" -- "%DLL_LOAD%" "%TARGET_APP%" %DLL_EXPORTS%
set EXE_CMD=%PIN_DIR%\pin.exe -t %PINTOOL% -m "%TRACED_MODULE%" -o %TAG_FILE% -s %SETTINGS_FILE% -b "%WATCH_BEFORE%" -- "%TARGET_APP%" "%EXE_ARGS%"


set start=%time%

;rem "Trace EXE"
if [%PE_TYPE%] == [exe] (
if [%IS_ADMIN%] == [A] (
%ADMIN_CMD% %EXE_CMD%
) else (
%EXE_CMD%
)
)
;rem "Trace DLL"
if [%PE_TYPE%] == [dll] (
if [%IS_ADMIN%] == [A] (
%ADMIN_CMD% %DLL_CMD%
) else (
%DLL_CMD%
)
)

set end=%time%

set options="tokens=1-4 delims=:.,"
for /f %options% %%a in ("%start%") do set start_h=%%a&set /a start_m=100%%b %% 100&set /a start_s=100%%c %% 100&set /a start_ms=100%%d %% 100
for /f %options% %%a in ("%end%") do set end_h=%%a&set /a end_m=100%%b %% 100&set /a end_s=100%%c %% 100&set /a end_ms=100%%d %% 100

set /a hours=%end_h%-%start_h%
set /a mins=%end_m%-%start_m%
set /a secs=%end_s%-%start_s%
set /a ms=%end_ms%-%start_ms%
if %ms% lss 0 set /a secs = %secs% - 1 & set /a ms = 100%ms%
if %secs% lss 0 set /a mins = %mins% - 1 & set /a secs = 60%secs%
if %mins% lss 0 set /a hours = %hours% - 1 & set /a mins = 60%mins%
if %hours% lss 0 set /a hours = 24%hours%
if 1%ms% lss 100 set ms=0%ms%

:: Mission accomplished
set /a totalsecs = %hours%*3600 + %mins%*60 + %secs%
echo command took %hours%:%mins%:%secs%.%ms% (%totalsecs%.%ms%s total)


if [%IS_ADMIN%] == [A] (
rem In Admin mode, a new console should be created. Pause only if it failed, in order to display the error:
if NOT %ERRORLEVEL% EQU 0 pause
) else (
if %ERRORLEVEL% EQU 0 echo [OK] PIN tracing finished: the traced application terminated.
rem Pausing script after the application is executed is useful to see all eventual printed messages and for troubleshooting
pause
)
:finish

0 comments on commit b07b7e9

Please sign in to comment.