Skip to content

Commit

Permalink
Many changes, bad programmer!
Browse files Browse the repository at this point in the history
Just copying the history from the source:

recognize the standard handle defines in WriteFile;
minor speed improvement by caching GetConsoleMode;
keep track of three handles (ostensibly stdout, stderr and a file);
test a DOS header exists before writing to e_oemid;
more flexible/robust handling of data directories;
files writing to the console will always succeed;
log: use API file functions and a custom printf;
     add a blank line between processes;
     set function name for MyWriteConsoleA;
scan imports from "kernel32" (without extension);
added dynamic environment variable CLICOLOR;
removed _hwrite (it's the same address as _lwrite);
join multibyte characters split across separate writes;
remove wcstok, avoiding potential interference with the host;
similarly, use a private heap instead of malloc.
  • Loading branch information
adoxa committed Jul 25, 2017
1 parent 2f18f10 commit 40f59c5
Show file tree
Hide file tree
Showing 10 changed files with 934 additions and 428 deletions.
649 changes: 436 additions & 213 deletions ANSI.c

Large diffs are not rendered by default.

25 changes: 14 additions & 11 deletions ansicon.c
Expand Up @@ -87,7 +87,7 @@
add error codes to some message.
*/

#define PDATE L"26 February, 2014"
#define PDATE L"24 December, 2015"

#include "ansicon.h"
#include "version.h"
Expand Down Expand Up @@ -169,6 +169,7 @@ int my_fputws( const wchar_t* s, FILE* f )
#define _putws( s ) my_fputws( s L"\n", stdout )


HANDLE hHeap;
#if defined(_WIN64)
LPTSTR DllNameType;
#endif
Expand All @@ -183,7 +184,7 @@ BOOL Inject( LPPROCESS_INFORMATION ppi, BOOL* gui, LPCTSTR app )
#ifdef _WIN64
if (app != NULL)
#endif
DEBUGSTR( 1, L"%s (%lu)", app, ppi->dwProcessId );
DEBUGSTR( 1, "%S (%u)", app, ppi->dwProcessId );
type = ProcessType( ppi, &base, gui );
if (type <= 0)
{
Expand Down Expand Up @@ -230,7 +231,7 @@ void RemoteLoad( LPPROCESS_INFORMATION ppi, LPCTSTR app )
int type;
#endif

DEBUGSTR( 1, L"%s (%lu)", app, ppi->dwProcessId );
DEBUGSTR( 1, "%S (%u)", app, ppi->dwProcessId );

// Find the base address of kernel32.dll.
ticks = GetTickCount();
Expand All @@ -242,7 +243,7 @@ void RemoteLoad( LPPROCESS_INFORMATION ppi, LPCTSTR app )
#ifndef _WIN64
if (err == ERROR_PARTIAL_COPY)
{
DEBUGSTR( 1, L" Ignoring 64-bit process (use x64\\ansicon)" );
DEBUGSTR( 1, " Ignoring 64-bit process (use x64\\ansicon)" );
fputws( L"ANSICON: parent is 64-bit (use x64\\ansicon).\n", stderr );
return;
}
Expand All @@ -251,10 +252,10 @@ void RemoteLoad( LPPROCESS_INFORMATION ppi, LPCTSTR app )
// two seconds to avoid a potentially infinite loop.
if (err == ERROR_BAD_LENGTH && GetTickCount() - ticks < 2000)
{
Sleep( 0 );
Sleep( 1 );
continue;
}
DEBUGSTR( 1, L" Unable to create snapshot (%lu)", err );
DEBUGSTR( 1, " Unable to create snapshot (%u)", err );
no_go:
fputws( L"ANSICON: unable to inject into parent.\n", stderr );
return;
Expand All @@ -272,7 +273,7 @@ void RemoteLoad( LPPROCESS_INFORMATION ppi, LPCTSTR app )
CloseHandle( hSnap );
if (LLW == NULL)
{
DEBUGSTR( 1, L" Unable to locate kernel32.dll (%lu)", GetLastError() );
DEBUGSTR( 1, " Unable to locate kernel32.dll" );
goto no_go;
}

Expand All @@ -292,7 +293,7 @@ void RemoteLoad( LPPROCESS_INFORMATION ppi, LPCTSTR app )
mem = VirtualAllocEx( ppi->hProcess, NULL, len, MEM_COMMIT, PAGE_READWRITE );
if (mem == NULL)
{
DEBUGSTR( 1, L" Unable to allocate virtual memory (%lu)", GetLastError() );
DEBUGSTR(1, " Failed to allocate virtual memory (%u)", GetLastError());
goto no_go;
}
WriteProcMem( mem, DllName, TSIZE(len + 11) );
Expand Down Expand Up @@ -357,6 +358,8 @@ int main( void )
}
}

hHeap = HeapCreate( 0, 0, 65 * 1024 );

prog = get_program_name( NULL );
*buf = '\0';
GetEnvironmentVariable( L"ANSICON_LOG", buf, lenof(buf) );
Expand All @@ -369,7 +372,7 @@ int main( void )
pi.hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId );
if (pi.hProcess == NULL)
{
DEBUGSTR( 1, L" Unable to open process %lu (%lu)",
DEBUGSTR( 1, " Unable to open process %u (%u)",
pi.dwProcessId, GetLastError() );
}
else
Expand Down Expand Up @@ -738,7 +741,7 @@ BOOL GetParentProcessInfo( LPPROCESS_INFORMATION ppi, LPTSTR name )
hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if (hSnap == INVALID_HANDLE_VALUE)
{
DEBUGSTR( 1, L"Failed to create snapshot (%lu)", GetLastError() );
DEBUGSTR( 1, "Failed to create snapshot (%u)", GetLastError() );
return FALSE;
}

Expand All @@ -747,7 +750,7 @@ BOOL GetParentProcessInfo( LPPROCESS_INFORMATION ppi, LPTSTR name )
CloseHandle( hSnap );
if (!fOk)
{
DEBUGSTR( 1, L"Failed to locate parent" );
DEBUGSTR( 1, "Failed to locate parent" );
return FALSE;
}

Expand Down
4 changes: 3 additions & 1 deletion ansicon.h
Expand Up @@ -35,6 +35,7 @@
// Macro for adding pointers/DWORDs together without C arithmetic interfering
#define MakeVA( cast, offset ) (cast)((DWORD_PTR)pDosHeader + (DWORD)(offset))

#define DATADIRS OptionalHeader.NumberOfRvaAndSizes
#define EXPORTDIR OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
#define IMPORTDIR OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
#define BOUNDDIR OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT]
Expand All @@ -61,6 +62,7 @@ DWORD GetProcRVA( LPCTSTR, LPCSTR, int );
DWORD GetProcRVA( LPCTSTR, LPCSTR );
#endif

extern HANDLE hHeap;

extern TCHAR prog_path[MAX_PATH];
extern LPTSTR prog;
Expand All @@ -74,6 +76,6 @@ extern char* ansi_bits;
void set_ansi_dll( void );

extern int log_level;
void DEBUGSTR( int level, LPTSTR szFormat, ... );
void DEBUGSTR( int level, LPCSTR szFormat, ... );

#endif
110 changes: 70 additions & 40 deletions injdll.c
Expand Up @@ -38,11 +38,35 @@ static PVOID FindMem( HANDLE hProcess, PBYTE base, DWORD len )
}


// Count the imports directly (including the terminator), since the size of the
// import directory is not necessarily correct (Windows doesn't use it at all).
static DWORD sizeof_imports( LPPROCESS_INFORMATION ppi,
PBYTE pBase, DWORD rImports )
{
IMAGE_IMPORT_DESCRIPTOR import;
PIMAGE_IMPORT_DESCRIPTOR pImports;
DWORD cnt;

if (rImports == 0)
return 0;

pImports = (PIMAGE_IMPORT_DESCRIPTOR)(pBase + rImports);
cnt = 0;
do
{
++cnt;
ReadProcVar( pImports++, &import );
} while (import.Name != 0);

return cnt * sizeof(import);
}


void InjectDLL( LPPROCESS_INFORMATION ppi, PBYTE pBase )
{
DWORD rva;
PVOID pMem;
DWORD len;
DWORD len, import_size;
DWORD pr;
IMAGE_DOS_HEADER DosHeader;
IMAGE_NT_HEADERS NTHeader, *pNTHeader;
Expand All @@ -59,56 +83,59 @@ void InjectDLL( LPPROCESS_INFORMATION ppi, PBYTE pBase )
pNTHeader = (PIMAGE_NT_HEADERS)(pBase + DosHeader.e_lfanew);
ReadProcVar( pNTHeader, &NTHeader );

len = 4 * PTRSZ + ansi_len + sizeof(*pImports) + NTHeader.IMPORTDIR.Size;
pImports = malloc( len );
import_size = sizeof_imports( ppi, pBase, NTHeader.IMPORTDIR.VirtualAddress );
len = 2 * PTRSZ + ansi_len + sizeof(*pImports) + import_size;
pImports = HeapAlloc( hHeap, 0, len );
if (pImports == NULL)
{
DEBUGSTR( 1, L" Failed to allocate memory." );
DEBUGSTR( 1, " Failed to allocate memory" );
return;
}
pMem = FindMem( ppi->hProcess, pBase, len );
if (pMem == NULL)
{
DEBUGSTR( 1, L" Failed to allocate virtual memory." );
free( pImports );
DEBUGSTR( 1, " Failed to allocate virtual memory (%u)", GetLastError() );
HeapFree( hHeap, 0, pImports );
return;
}
rva = (DWORD)((PBYTE)pMem - pBase);

ip.pL = (PLONG_PTR)pImports;
*ip.pL++ = IMAGE_ORDINAL_FLAG + 1;
*ip.pL++ = 0;
*ip.pL++ = IMAGE_ORDINAL_FLAG + 1;
*ip.pL++ = 0;
memcpy( ip.pB, ansi_dll, ansi_len );
ip.pB += ansi_len;
ip.pI->OriginalFirstThunk = rva + 2 * PTRSZ;
ip.pI->OriginalFirstThunk = 0;
ip.pI->TimeDateStamp = 0;
ip.pI->ForwarderChain = 0;
ip.pI->Name = rva + 4 * PTRSZ;
ip.pI->Name = rva + 2 * PTRSZ;
ip.pI->FirstThunk = rva;
ReadProcMem( pBase + NTHeader.IMPORTDIR.VirtualAddress,
ip.pI + 1, NTHeader.IMPORTDIR.Size );
ReadProcMem( pBase+NTHeader.IMPORTDIR.VirtualAddress, ip.pI+1, import_size );
WriteProcMem( pMem, pImports, len );
free( pImports );
HeapFree( hHeap, 0, pImports );

// If there's no IAT, copy the original IDT (to allow writable ".idata").
if (NTHeader.IATDIR.VirtualAddress == 0)
if (NTHeader.DATADIRS > IMAGE_DIRECTORY_ENTRY_IAT &&
NTHeader.IATDIR.VirtualAddress == 0)
NTHeader.IATDIR = NTHeader.IMPORTDIR;

NTHeader.IMPORTDIR.VirtualAddress = rva + 4 * PTRSZ + ansi_len;
NTHeader.IMPORTDIR.Size += sizeof(*pImports);
NTHeader.IMPORTDIR.VirtualAddress = rva + 2 * PTRSZ + ansi_len;
//NTHeader.IMPORTDIR.Size += sizeof(*pImports);

// Remove bound imports, so the updated import table is used.
NTHeader.BOUNDDIR.VirtualAddress = 0;
NTHeader.BOUNDDIR.Size = 0;
if (NTHeader.DATADIRS > IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT)
{
NTHeader.BOUNDDIR.VirtualAddress = 0;
//NTHeader.BOUNDDIR.Size = 0;
}

VirtProtVar( pNTHeader, PAGE_READWRITE );
WriteProcVar( pNTHeader, &NTHeader );
VirtProtVar( pNTHeader, pr );

// Remove the IL-only flag on a managed process.
if (NTHeader.COMDIR.VirtualAddress != 0 && NTHeader.COMDIR.Size != 0)
if (NTHeader.DATADIRS > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR &&
NTHeader.COMDIR.VirtualAddress != 0)
{
pComHeader = (PIMAGE_COR20_HEADER)(pBase + NTHeader.COMDIR.VirtualAddress);
ReadProcVar( pComHeader, &ComHeader );
Expand All @@ -128,7 +155,7 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, PBYTE pBase )
{
DWORD rva;
PVOID pMem;
DWORD len;
DWORD len, import_size;
DWORD pr;
IMAGE_DOS_HEADER DosHeader;
IMAGE_NT_HEADERS32 NTHeader, *pNTHeader;
Expand All @@ -145,50 +172,53 @@ void InjectDLL32( LPPROCESS_INFORMATION ppi, PBYTE pBase )
pNTHeader = (PIMAGE_NT_HEADERS32)(pBase + DosHeader.e_lfanew);
ReadProcVar( pNTHeader, &NTHeader );

len = 16 + ansi_len + sizeof(*pImports) + NTHeader.IMPORTDIR.Size;
pImports = malloc( len );
import_size = sizeof_imports( ppi, pBase, NTHeader.IMPORTDIR.VirtualAddress );
len = 8 + ansi_len + sizeof(*pImports) + import_size;
pImports = HeapAlloc( hHeap, 0, len );
if (pImports == NULL)
{
DEBUGSTR( 1, L" Failed to allocate memory." );
DEBUGSTR( 1, " Failed to allocate memory" );
return;
}
pMem = FindMem( ppi->hProcess, pBase, len );
if (pMem == NULL)
{
DEBUGSTR( 1, L" Failed to allocate virtual memory." );
free( pImports );
DEBUGSTR( 1, " Failed to allocate virtual memory" );
HeapFree( hHeap, 0, pImports );
return;
}
rva = (DWORD)((PBYTE)pMem - pBase);

ip.pL = (PLONG)pImports;
*ip.pL++ = IMAGE_ORDINAL_FLAG32 + 1;
*ip.pL++ = 0;
*ip.pL++ = IMAGE_ORDINAL_FLAG32 + 1;
*ip.pL++ = 0;
memcpy( ip.pB, ansi_dll, ansi_len );
ip.pB += ansi_len;
ip.pI->OriginalFirstThunk = rva + 8;
ip.pI->OriginalFirstThunk = 0;
ip.pI->TimeDateStamp = 0;
ip.pI->ForwarderChain = 0;
ip.pI->Name = rva + 16;
ip.pI->Name = rva + 8;
ip.pI->FirstThunk = rva;
ReadProcMem( pBase + NTHeader.IMPORTDIR.VirtualAddress,
ip.pI + 1, NTHeader.IMPORTDIR.Size );
ReadProcMem( pBase+NTHeader.IMPORTDIR.VirtualAddress, ip.pI+1, import_size );
WriteProcMem( pMem, pImports, len );
free( pImports );
HeapFree( hHeap, 0, pImports );

if (NTHeader.IATDIR.VirtualAddress == 0)
if (NTHeader.DATADIRS > IMAGE_DIRECTORY_ENTRY_IAT &&
NTHeader.IATDIR.VirtualAddress == 0)
NTHeader.IATDIR = NTHeader.IMPORTDIR;
NTHeader.IMPORTDIR.VirtualAddress = rva + 16 + ansi_len;
NTHeader.IMPORTDIR.Size += sizeof(*pImports);
NTHeader.BOUNDDIR.VirtualAddress = 0;
NTHeader.BOUNDDIR.Size = 0;
NTHeader.IMPORTDIR.VirtualAddress = rva + 8 + ansi_len;
//NTHeader.IMPORTDIR.Size += sizeof(*pImports);
if (NTHeader.DATADIRS > IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT)
{
NTHeader.BOUNDDIR.VirtualAddress = 0;
//NTHeader.BOUNDDIR.Size = 0;
}
VirtProtVar( pNTHeader, PAGE_READWRITE );
WriteProcVar( pNTHeader, &NTHeader );
VirtProtVar( pNTHeader, pr );

if (NTHeader.COMDIR.VirtualAddress != 0 && NTHeader.COMDIR.Size != 0)
if (NTHeader.DATADIRS > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR &&
NTHeader.COMDIR.VirtualAddress != 0)
{
pComHeader = (PIMAGE_COR20_HEADER)(pBase + NTHeader.COMDIR.VirtualAddress);
ReadProcVar( pComHeader, &ComHeader );
Expand Down Expand Up @@ -233,7 +263,7 @@ static PBYTE get_ntdll( LPPROCESS_INFORMATION ppi )
}
}

DEBUGSTR( 1, L" Failed to find ntdll.dll!" );
DEBUGSTR( 1, " Failed to find ntdll.dll!" );
return NULL;
}

Expand Down Expand Up @@ -266,7 +296,7 @@ void InjectDLL64( LPPROCESS_INFORMATION ppi )
PAGE_EXECUTE_READ );
if (pMem == NULL)
{
DEBUGSTR( 1, L" Failed to allocate virtual memory (%lu)", GetLastError() );
DEBUGSTR(1, " Failed to allocate virtual memory (%u)", GetLastError());
return;
}

Expand Down
8 changes: 4 additions & 4 deletions procrva.c
Expand Up @@ -43,10 +43,10 @@ DWORD GetProcRVA( LPCTSTR module, LPCSTR func )
if (hMod == NULL)
{
#ifdef _WIN64
DEBUGSTR( 1, L"Unable to load %d-bit %s (%lu)!",
DEBUGSTR( 1, "Unable to load %u-bit %S (%u)!",
bits, module, GetLastError() );
#else
DEBUGSTR( 1, L"Unable to load %s (%lu)!", module, GetLastError() );
DEBUGSTR( 1, "Unable to load %S (%u)!", module, GetLastError() );
#endif
return 0;
}
Expand All @@ -70,9 +70,9 @@ DWORD GetProcRVA( LPCTSTR module, LPCSTR func )
if (pFunc == NULL)
{
#ifdef _WIN64
DEBUGSTR( 1, L"Could not find %d-bit %s!", bits, func );
DEBUGSTR( 1, "Could not find %u-bit %s!", bits, func );
#else
DEBUGSTR( 1, L"Could not find %s!", func );
DEBUGSTR( 1, "Could not find %s!", func );
#endif
rva = 0;
}
Expand Down

0 comments on commit 40f59c5

Please sign in to comment.