mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
* OnlineChecks: updated VirusTotal and virusscan.jotti.org uploaders
* OnlineChecks: added hash checking git-svn-id: svn://svn.code.sf.net/p/processhacker/code@4950 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
@@ -2,6 +2,8 @@ Process Hacker
|
||||
|
||||
2.27
|
||||
* NEW/IMPROVED:
|
||||
* Updated OnlineChecks plugin:
|
||||
* 2012-01-16: Updated VirusTotal uploader and added hash checking
|
||||
* FIXED:
|
||||
|
||||
2.26
|
||||
|
||||
@@ -584,10 +584,10 @@ CAPTION "About"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,213,174,50,14
|
||||
ICON IDI_PROCESSHACKER,IDC_STATIC,16,15,21,20
|
||||
ICON IDI_PROCESSHACKER,IDC_STATIC,16,15,20,20
|
||||
LTEXT "Process Hacker",IDC_ABOUT_NAME,45,14,192,8
|
||||
LTEXT "Licensed under the GNU GPL, v3.",IDC_STATIC,45,27,193,8
|
||||
LTEXT "Copyright (c) 2008-2011 wj32",IDC_STATIC,15,40,97,8
|
||||
LTEXT "Copyright (c) 2008-2012 wj32",IDC_STATIC,15,40,97,8
|
||||
PUSHBUTTON "Diagnostics",IDC_DIAGNOSTICS,160,174,50,14
|
||||
CONTROL "<a href=""http://sourceforge.net/projects/processhacker"">Process Hacker on SourceForge.net</a>",IDC_LINK_SF,
|
||||
"SysLink",WS_TABSTOP,7,177,130,11
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
1.3
|
||||
* 2012-01-16: Updated VirusTotal uploader and added hash checking
|
||||
|
||||
1.2
|
||||
* 2011-06-22: Added Comodo Instant Malware Analysis
|
||||
|
||||
|
||||
@@ -53,8 +53,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,2,0,0
|
||||
PRODUCTVERSION 1,2,0,0
|
||||
FILEVERSION 1,3,0,0
|
||||
PRODUCTVERSION 1,3,0,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -71,12 +71,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "wj32"
|
||||
VALUE "FileDescription", "Online Checks plugin for Process Hacker"
|
||||
VALUE "FileVersion", "1.2"
|
||||
VALUE "FileVersion", "1.3"
|
||||
VALUE "InternalName", "OnlineChecks"
|
||||
VALUE "LegalCopyright", "Licensed under the GNU GPL, v3."
|
||||
VALUE "OriginalFilename", "OnlineChecks.dll"
|
||||
VALUE "ProductName", "Online Checks plugin for Process Hacker"
|
||||
VALUE "ProductVersion", "1.2"
|
||||
VALUE "ProductVersion", "1.3"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -163,11 +163,13 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.c" />
|
||||
<ClCompile Include="sha256.c" />
|
||||
<ClCompile Include="upload.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="onlnchk.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="sha256.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="OnlineChecks.rc" />
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
<ClCompile Include="upload.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sha256.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="onlnchk.h">
|
||||
@@ -29,6 +32,9 @@
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sha256.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="OnlineChecks.rc">
|
||||
|
||||
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* FIPS-180-2 compliant SHA-256 implementation
|
||||
*
|
||||
* Copyright (C) 2001-2003 Christophe Devine
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "sha256.h"
|
||||
|
||||
#define GET_UINT32(n,b,i) \
|
||||
{ \
|
||||
(n) = ( (uint32) (b)[(i) ] << 24 ) \
|
||||
| ( (uint32) (b)[(i) + 1] << 16 ) \
|
||||
| ( (uint32) (b)[(i) + 2] << 8 ) \
|
||||
| ( (uint32) (b)[(i) + 3] ); \
|
||||
}
|
||||
|
||||
#define PUT_UINT32(n,b,i) \
|
||||
{ \
|
||||
(b)[(i) ] = (uint8) ( (n) >> 24 ); \
|
||||
(b)[(i) + 1] = (uint8) ( (n) >> 16 ); \
|
||||
(b)[(i) + 2] = (uint8) ( (n) >> 8 ); \
|
||||
(b)[(i) + 3] = (uint8) ( (n) ); \
|
||||
}
|
||||
|
||||
void sha256_starts( sha256_context *ctx )
|
||||
{
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
ctx->state[0] = 0x6A09E667;
|
||||
ctx->state[1] = 0xBB67AE85;
|
||||
ctx->state[2] = 0x3C6EF372;
|
||||
ctx->state[3] = 0xA54FF53A;
|
||||
ctx->state[4] = 0x510E527F;
|
||||
ctx->state[5] = 0x9B05688C;
|
||||
ctx->state[6] = 0x1F83D9AB;
|
||||
ctx->state[7] = 0x5BE0CD19;
|
||||
}
|
||||
|
||||
void sha256_process( sha256_context *ctx, uint8 data[64] )
|
||||
{
|
||||
uint32 temp1, temp2, W[64];
|
||||
uint32 A, B, C, D, E, F, G, H;
|
||||
|
||||
GET_UINT32( W[0], data, 0 );
|
||||
GET_UINT32( W[1], data, 4 );
|
||||
GET_UINT32( W[2], data, 8 );
|
||||
GET_UINT32( W[3], data, 12 );
|
||||
GET_UINT32( W[4], data, 16 );
|
||||
GET_UINT32( W[5], data, 20 );
|
||||
GET_UINT32( W[6], data, 24 );
|
||||
GET_UINT32( W[7], data, 28 );
|
||||
GET_UINT32( W[8], data, 32 );
|
||||
GET_UINT32( W[9], data, 36 );
|
||||
GET_UINT32( W[10], data, 40 );
|
||||
GET_UINT32( W[11], data, 44 );
|
||||
GET_UINT32( W[12], data, 48 );
|
||||
GET_UINT32( W[13], data, 52 );
|
||||
GET_UINT32( W[14], data, 56 );
|
||||
GET_UINT32( W[15], data, 60 );
|
||||
|
||||
#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
|
||||
#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
|
||||
|
||||
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
|
||||
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
|
||||
|
||||
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
|
||||
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
|
||||
|
||||
#define F0(x,y,z) ((x & y) | (z & (x | y)))
|
||||
#define F1(x,y,z) (z ^ (x & (y ^ z)))
|
||||
|
||||
#define R(t) \
|
||||
( \
|
||||
W[t] = S1(W[t - 2]) + W[t - 7] + \
|
||||
S0(W[t - 15]) + W[t - 16] \
|
||||
)
|
||||
|
||||
#define P(a,b,c,d,e,f,g,h,x,K) \
|
||||
{ \
|
||||
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
|
||||
temp2 = S2(a) + F0(a,b,c); \
|
||||
d += temp1; h = temp1 + temp2; \
|
||||
}
|
||||
|
||||
A = ctx->state[0];
|
||||
B = ctx->state[1];
|
||||
C = ctx->state[2];
|
||||
D = ctx->state[3];
|
||||
E = ctx->state[4];
|
||||
F = ctx->state[5];
|
||||
G = ctx->state[6];
|
||||
H = ctx->state[7];
|
||||
|
||||
P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );
|
||||
P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );
|
||||
P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );
|
||||
P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );
|
||||
P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );
|
||||
P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );
|
||||
P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );
|
||||
P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );
|
||||
P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );
|
||||
P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );
|
||||
P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );
|
||||
P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );
|
||||
P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );
|
||||
P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );
|
||||
P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );
|
||||
P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );
|
||||
P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );
|
||||
P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );
|
||||
P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );
|
||||
P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );
|
||||
P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );
|
||||
P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );
|
||||
P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );
|
||||
P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );
|
||||
P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );
|
||||
P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );
|
||||
P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );
|
||||
P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );
|
||||
P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );
|
||||
P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );
|
||||
P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );
|
||||
P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );
|
||||
P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );
|
||||
P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );
|
||||
P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );
|
||||
P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );
|
||||
P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );
|
||||
P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );
|
||||
P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );
|
||||
P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );
|
||||
P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );
|
||||
P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );
|
||||
P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );
|
||||
P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );
|
||||
P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );
|
||||
P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );
|
||||
P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );
|
||||
P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );
|
||||
P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );
|
||||
P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );
|
||||
P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );
|
||||
P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );
|
||||
P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );
|
||||
P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );
|
||||
P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );
|
||||
P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );
|
||||
P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );
|
||||
P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );
|
||||
P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );
|
||||
P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );
|
||||
P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );
|
||||
P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );
|
||||
P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );
|
||||
P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );
|
||||
|
||||
ctx->state[0] += A;
|
||||
ctx->state[1] += B;
|
||||
ctx->state[2] += C;
|
||||
ctx->state[3] += D;
|
||||
ctx->state[4] += E;
|
||||
ctx->state[5] += F;
|
||||
ctx->state[6] += G;
|
||||
ctx->state[7] += H;
|
||||
}
|
||||
|
||||
void sha256_update( sha256_context *ctx, uint8 *input, uint32 length )
|
||||
{
|
||||
uint32 left, fill;
|
||||
|
||||
if( ! length ) return;
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += length;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if( ctx->total[0] < length )
|
||||
ctx->total[1]++;
|
||||
|
||||
if( left && length >= fill )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left),
|
||||
(void *) input, fill );
|
||||
sha256_process( ctx, ctx->buffer );
|
||||
length -= fill;
|
||||
input += fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while( length >= 64 )
|
||||
{
|
||||
sha256_process( ctx, input );
|
||||
length -= 64;
|
||||
input += 64;
|
||||
}
|
||||
|
||||
if( length )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left),
|
||||
(void *) input, length );
|
||||
}
|
||||
}
|
||||
|
||||
static uint8 sha256_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
void sha256_finish( sha256_context *ctx, uint8 digest[32] )
|
||||
{
|
||||
uint32 last, padn;
|
||||
uint32 high, low;
|
||||
uint8 msglen[8];
|
||||
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32( high, msglen, 0 );
|
||||
PUT_UINT32( low, msglen, 4 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
sha256_update( ctx, sha256_padding, padn );
|
||||
sha256_update( ctx, msglen, 8 );
|
||||
|
||||
PUT_UINT32( ctx->state[0], digest, 0 );
|
||||
PUT_UINT32( ctx->state[1], digest, 4 );
|
||||
PUT_UINT32( ctx->state[2], digest, 8 );
|
||||
PUT_UINT32( ctx->state[3], digest, 12 );
|
||||
PUT_UINT32( ctx->state[4], digest, 16 );
|
||||
PUT_UINT32( ctx->state[5], digest, 20 );
|
||||
PUT_UINT32( ctx->state[6], digest, 24 );
|
||||
PUT_UINT32( ctx->state[7], digest, 28 );
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* those are the standard FIPS-180-2 test vectors
|
||||
*/
|
||||
|
||||
static char *msg[] =
|
||||
{
|
||||
"abc",
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *val[] =
|
||||
{
|
||||
"ba7816bf8f01cfea414140de5dae2223" \
|
||||
"b00361a396177a9cb410ff61f20015ad",
|
||||
"248d6a61d20638b8e5c026930c3e6039" \
|
||||
"a33ce45964ff2167f6ecedd419db06c1",
|
||||
"cdc76e5c9914fb9281a1c7e284d73e67" \
|
||||
"f1809a48a497200e046d39ccc7112cd0"
|
||||
};
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
FILE *f;
|
||||
int i, j;
|
||||
char output[65];
|
||||
sha256_context ctx;
|
||||
unsigned char buf[1000];
|
||||
unsigned char sha256sum[32];
|
||||
|
||||
if( argc < 2 )
|
||||
{
|
||||
printf( "\n SHA-256 Validation Tests:\n\n" );
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
printf( " Test %d ", i + 1 );
|
||||
|
||||
sha256_starts( &ctx );
|
||||
|
||||
if( i < 2 )
|
||||
{
|
||||
sha256_update( &ctx, (uint8 *) msg[i],
|
||||
strlen( msg[i] ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
memset( buf, 'a', 1000 );
|
||||
|
||||
for( j = 0; j < 1000; j++ )
|
||||
{
|
||||
sha256_update( &ctx, (uint8 *) buf, 1000 );
|
||||
}
|
||||
}
|
||||
|
||||
sha256_finish( &ctx, sha256sum );
|
||||
|
||||
for( j = 0; j < 32; j++ )
|
||||
{
|
||||
sprintf( output + j * 2, "%02x", sha256sum[j] );
|
||||
}
|
||||
|
||||
if( memcmp( output, val[i], 64 ) )
|
||||
{
|
||||
printf( "failed!\n" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
printf( "passed.\n" );
|
||||
}
|
||||
|
||||
printf( "\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ! ( f = fopen( argv[1], "rb" ) ) )
|
||||
{
|
||||
perror( "fopen" );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
sha256_starts( &ctx );
|
||||
|
||||
while( ( i = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
|
||||
{
|
||||
sha256_update( &ctx, buf, i );
|
||||
}
|
||||
|
||||
sha256_finish( &ctx, sha256sum );
|
||||
|
||||
for( j = 0; j < 32; j++ )
|
||||
{
|
||||
printf( "%02x", sha256sum[j] );
|
||||
}
|
||||
|
||||
printf( " %s\n", argv[1] );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef _SHA256_H
|
||||
#define _SHA256_H
|
||||
|
||||
#ifndef uint8
|
||||
#define uint8 unsigned char
|
||||
#endif
|
||||
|
||||
#ifndef uint32
|
||||
#define uint32 unsigned long int
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 total[2];
|
||||
uint32 state[8];
|
||||
uint8 buffer[64];
|
||||
}
|
||||
sha256_context;
|
||||
|
||||
void sha256_starts( sha256_context *ctx );
|
||||
void sha256_update( sha256_context *ctx, uint8 *input, uint32 length );
|
||||
void sha256_finish( sha256_context *ctx, uint8 digest[32] );
|
||||
|
||||
#endif /* sha256.h */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Process Hacker Online Checks -
|
||||
* uploader
|
||||
*
|
||||
* Copyright (C) 2010-2011 wj32
|
||||
* Copyright (C) 2010-2012 wj32
|
||||
*
|
||||
* This file is part of Process Hacker.
|
||||
*
|
||||
@@ -23,8 +23,12 @@
|
||||
#include <phdk.h>
|
||||
#include <wininet.h>
|
||||
#include "onlnchk.h"
|
||||
#include "sha256.h"
|
||||
#include "resource.h"
|
||||
|
||||
#define HASH_SHA1 1
|
||||
#define HASH_SHA256 2
|
||||
|
||||
#define UM_LAUNCH_COMMAND (WM_APP + 1)
|
||||
#define UM_ERROR (WM_APP + 2)
|
||||
|
||||
@@ -35,6 +39,7 @@ typedef struct _UPLOAD_CONTEXT
|
||||
PPH_STRING FileName;
|
||||
ULONG Service;
|
||||
HWND WindowHandle;
|
||||
PH_QUEUED_LOCK Lock;
|
||||
HANDLE ThreadHandle;
|
||||
|
||||
PPH_STRING LaunchCommand;
|
||||
@@ -45,6 +50,8 @@ typedef struct _SERVICE_INFO
|
||||
{
|
||||
ULONG Id;
|
||||
PWSTR HostName;
|
||||
ULONG HostPort;
|
||||
ULONG HostFlags;
|
||||
PWSTR UploadObjectName;
|
||||
PSTR FileNameFieldName;
|
||||
} SERVICE_INFO, *PSERVICE_INFO;
|
||||
@@ -58,9 +65,9 @@ INT_PTR CALLBACK UploadDlgProc(
|
||||
|
||||
SERVICE_INFO UploadServiceInfo[] =
|
||||
{
|
||||
{ UPLOAD_SERVICE_VIRUSTOTAL, L"www.virustotal.com", L"/file-upload/file_upload", "file" },
|
||||
{ UPLOAD_SERVICE_JOTTI, L"virusscan.jotti.org", L"/processupload.php", "scanfile" },
|
||||
{ UPLOAD_SERVICE_CIMA, L"camas.comodo.com", L"/cgi-bin/submit", "file" }
|
||||
{ UPLOAD_SERVICE_VIRUSTOTAL, L"www.virustotal.com", INTERNET_DEFAULT_HTTPS_PORT, INTERNET_FLAG_SECURE, L"???", "file" },
|
||||
{ UPLOAD_SERVICE_JOTTI, L"virusscan.jotti.org", INTERNET_DEFAULT_HTTP_PORT, 0, L"/processupload.php", "scanfile" },
|
||||
{ UPLOAD_SERVICE_CIMA, L"camas.comodo.com", INTERNET_DEFAULT_HTTP_PORT, 0, L"/cgi-bin/submit", "file" }
|
||||
};
|
||||
|
||||
PUPLOAD_CONTEXT CreateUploadContext(
|
||||
@@ -144,8 +151,24 @@ static VOID RaiseUploadError(
|
||||
|
||||
PhSwapReference(&errorMessage, NULL);
|
||||
|
||||
PhAcquireQueuedLockExclusive(&Context->Lock);
|
||||
|
||||
if (Context->WindowHandle)
|
||||
PostMessage(Context->WindowHandle, UM_ERROR, 0, 0);
|
||||
|
||||
PhReleaseQueuedLockExclusive(&Context->Lock);
|
||||
}
|
||||
|
||||
static VOID SendLaunchCommand(
|
||||
__in PUPLOAD_CONTEXT Context
|
||||
)
|
||||
{
|
||||
PhAcquireQueuedLockExclusive(&Context->Lock);
|
||||
|
||||
if (Context->WindowHandle)
|
||||
PostMessage(Context->WindowHandle, UM_LAUNCH_COMMAND, 0, 0);
|
||||
|
||||
PhReleaseQueuedLockExclusive(&Context->Lock);
|
||||
}
|
||||
|
||||
static PSERVICE_INFO GetUploadServiceInfo(
|
||||
@@ -163,6 +186,202 @@ static PSERVICE_INFO GetUploadServiceInfo(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BOOLEAN PerformSubRequest(
|
||||
__in PUPLOAD_CONTEXT Context,
|
||||
__in PWSTR HostName,
|
||||
__in PWSTR ObjectName,
|
||||
__out_bcount(BufferLength) PVOID Buffer,
|
||||
__in ULONG BufferLength,
|
||||
__out PULONG ReturnLength
|
||||
)
|
||||
{
|
||||
BOOLEAN result = FALSE;
|
||||
PPH_STRING userAgent;
|
||||
HINTERNET internetHandle = NULL;
|
||||
HINTERNET connectHandle = NULL;
|
||||
HINTERNET requestHandle = NULL;
|
||||
|
||||
// Create a user agent string.
|
||||
{
|
||||
PPH_STRING phVersion;
|
||||
|
||||
phVersion = PhGetPhVersion();
|
||||
userAgent = PhConcatStrings2(L"Process Hacker ", phVersion->Buffer);
|
||||
PhDereferenceObject(phVersion);
|
||||
}
|
||||
|
||||
// Create the internet handle.
|
||||
|
||||
internetHandle = InternetOpen(userAgent->Buffer, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
|
||||
PhDereferenceObject(userAgent);
|
||||
|
||||
if (!internetHandle)
|
||||
{
|
||||
RaiseUploadError(Context, L"Unable to initialize internet access", GetLastError());
|
||||
goto ExitCleanup;
|
||||
}
|
||||
|
||||
// Set the timeouts.
|
||||
{
|
||||
ULONG timeout = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
InternetSetOption(internetHandle, INTERNET_OPTION_CONNECT_TIMEOUT, &timeout, sizeof(ULONG));
|
||||
InternetSetOption(internetHandle, INTERNET_OPTION_SEND_TIMEOUT, &timeout, sizeof(ULONG));
|
||||
InternetSetOption(internetHandle, INTERNET_OPTION_RECEIVE_TIMEOUT, &timeout, sizeof(ULONG));
|
||||
InternetSetOption(internetHandle, INTERNET_OPTION_DATA_SEND_TIMEOUT, &timeout, sizeof(ULONG));
|
||||
InternetSetOption(internetHandle, INTERNET_OPTION_DATA_RECEIVE_TIMEOUT, &timeout, sizeof(ULONG));
|
||||
}
|
||||
|
||||
// Connect to the online service.
|
||||
|
||||
connectHandle = InternetConnect(
|
||||
internetHandle,
|
||||
HostName,
|
||||
80,
|
||||
NULL,
|
||||
NULL,
|
||||
INTERNET_SERVICE_HTTP,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
if (!connectHandle)
|
||||
{
|
||||
RaiseUploadError(Context, L"Unable to connect to the service", GetLastError());
|
||||
goto ExitCleanup;
|
||||
}
|
||||
|
||||
// Create the request.
|
||||
|
||||
{
|
||||
static PWSTR acceptTypes[2] = { L"*/*", NULL };
|
||||
|
||||
requestHandle = HttpOpenRequest(
|
||||
connectHandle,
|
||||
L"GET",
|
||||
ObjectName,
|
||||
L"HTTP/1.1",
|
||||
L"",
|
||||
acceptTypes,
|
||||
INTERNET_FLAG_RELOAD,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
if (!requestHandle)
|
||||
{
|
||||
RaiseUploadError(Context, L"Unable to create the request", GetLastError());
|
||||
goto ExitCleanup;
|
||||
}
|
||||
|
||||
// Send the request.
|
||||
|
||||
if (!HttpSendRequest(requestHandle, NULL, 0, NULL, 0))
|
||||
{
|
||||
RaiseUploadError(Context, L"Unable to send the request", GetLastError());
|
||||
goto ExitCleanup;
|
||||
}
|
||||
|
||||
// Handle service-specific actions.
|
||||
|
||||
if (!InternetReadFile(requestHandle, Buffer, BufferLength, ReturnLength))
|
||||
{
|
||||
RaiseUploadError(Context, L"Unable to complete the request", GetLastError());
|
||||
goto ExitCleanup;
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
|
||||
ExitCleanup:
|
||||
if (requestHandle)
|
||||
InternetCloseHandle(requestHandle);
|
||||
if (connectHandle)
|
||||
InternetCloseHandle(connectHandle);
|
||||
if (internetHandle)
|
||||
InternetCloseHandle(internetHandle);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static NTSTATUS HashFileAndResetPosition(
|
||||
__in HANDLE FileHandle,
|
||||
__in PLARGE_INTEGER FileSize,
|
||||
__in ULONG Algorithm,
|
||||
__out PVOID Hash
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
UCHAR buffer[PAGE_SIZE * 4];
|
||||
IO_STATUS_BLOCK iosb;
|
||||
PH_HASH_CONTEXT hashContext;
|
||||
sha256_context sha256;
|
||||
ULONG64 bytesRemaining;
|
||||
FILE_POSITION_INFORMATION positionInfo;
|
||||
|
||||
bytesRemaining = FileSize->QuadPart;
|
||||
|
||||
switch (Algorithm)
|
||||
{
|
||||
case HASH_SHA1:
|
||||
PhInitializeHash(&hashContext, Sha1HashAlgorithm);
|
||||
break;
|
||||
case HASH_SHA256:
|
||||
sha256_starts(&sha256);
|
||||
break;
|
||||
}
|
||||
|
||||
while (bytesRemaining)
|
||||
{
|
||||
status = NtReadFile(
|
||||
FileHandle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&iosb,
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
break;
|
||||
|
||||
switch (Algorithm)
|
||||
{
|
||||
case HASH_SHA1:
|
||||
PhUpdateHash(&hashContext, buffer, (ULONG)iosb.Information);
|
||||
break;
|
||||
case HASH_SHA256:
|
||||
sha256_update(&sha256, (PUCHAR)buffer, (ULONG)iosb.Information);
|
||||
break;
|
||||
}
|
||||
|
||||
bytesRemaining -= (ULONG)iosb.Information;
|
||||
}
|
||||
|
||||
if (status == STATUS_END_OF_FILE)
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
switch (Algorithm)
|
||||
{
|
||||
case HASH_SHA1:
|
||||
PhFinalHash(&hashContext, Hash, 20, NULL);
|
||||
break;
|
||||
case HASH_SHA256:
|
||||
sha256_finish(&sha256, Hash);
|
||||
break;
|
||||
}
|
||||
|
||||
positionInfo.CurrentByteOffset.QuadPart = 0;
|
||||
status = NtSetInformationFile(FileHandle, &iosb, &positionInfo, sizeof(FILE_POSITION_INFORMATION), FilePositionInformation);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static NTSTATUS UploadWorkerThreadStart(
|
||||
__in PVOID Parameter
|
||||
)
|
||||
@@ -172,17 +391,21 @@ static NTSTATUS UploadWorkerThreadStart(
|
||||
PSERVICE_INFO serviceInfo;
|
||||
PPH_STRING userAgent;
|
||||
HANDLE fileHandle = NULL;
|
||||
LARGE_INTEGER fileSize64;
|
||||
ULONG fileSize;
|
||||
PPH_STRING objectName = NULL;
|
||||
HINTERNET internetHandle = NULL;
|
||||
HINTERNET connectHandle = NULL;
|
||||
HINTERNET requestHandle = NULL;
|
||||
PPH_STRING boundary = NULL;
|
||||
PPH_ANSI_STRING boundaryAnsi = NULL;
|
||||
PH_STRING_BUILDER headers = { 0 };
|
||||
PPH_ANSI_STRING baseFileNameAnsi;
|
||||
PPH_ANSI_STRING baseFileNameAnsi = NULL;
|
||||
PUCHAR data = NULL;
|
||||
ULONG dataLength = 0;
|
||||
ULONG dataCursor = 0;
|
||||
UCHAR buffer[PAGE_SIZE];
|
||||
ULONG bufferSize;
|
||||
|
||||
serviceInfo = GetUploadServiceInfo(context->Service);
|
||||
|
||||
@@ -206,8 +429,6 @@ static NTSTATUS UploadWorkerThreadStart(
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
LARGE_INTEGER fileSize64;
|
||||
|
||||
if (NT_SUCCESS(status = PhGetFileSize(fileHandle, &fileSize64)))
|
||||
{
|
||||
if (fileSize64.QuadPart > 20 * 1024 * 1024) // 20 MB
|
||||
@@ -226,6 +447,124 @@ static NTSTATUS UploadWorkerThreadStart(
|
||||
goto ExitCleanup;
|
||||
}
|
||||
|
||||
switch (context->Service)
|
||||
{
|
||||
case UPLOAD_SERVICE_VIRUSTOTAL:
|
||||
{
|
||||
UCHAR hash[32];
|
||||
PPH_STRING hashString;
|
||||
PPH_STRING subObjectName;
|
||||
PSTR uploadUrl;
|
||||
PSTR quote;
|
||||
|
||||
status = HashFileAndResetPosition(fileHandle, &fileSize64, HASH_SHA256, hash);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
RaiseUploadError(context, L"Unable to hash the file", RtlNtStatusToDosError(status));
|
||||
goto ExitCleanup;
|
||||
}
|
||||
|
||||
hashString = PhBufferToHexString(hash, 32);
|
||||
subObjectName = PhConcatStrings2(L"/file/upload/?sha256=", hashString->Buffer);
|
||||
|
||||
if (!PerformSubRequest(context, serviceInfo->HostName, subObjectName->Buffer, buffer, sizeof(buffer) - 1, &bufferSize))
|
||||
{
|
||||
PhDereferenceObject(hashString);
|
||||
PhDereferenceObject(subObjectName);
|
||||
goto ExitCleanup;
|
||||
}
|
||||
|
||||
PhDereferenceObject(subObjectName);
|
||||
|
||||
buffer[bufferSize] = 0;
|
||||
|
||||
if (strstr(buffer, "\"file_exists\": true"))
|
||||
{
|
||||
// No upload needed; show the results immediately.
|
||||
context->LaunchCommand = PhFormatString(L"http://www.virustotal.com/file/%s/analysis/", hashString->Buffer);
|
||||
PhDereferenceObject(hashString);
|
||||
SendLaunchCommand(context);
|
||||
goto ExitCleanup;
|
||||
}
|
||||
|
||||
PhDereferenceObject(hashString);
|
||||
|
||||
uploadUrl = strstr(buffer, "\"upload_url\": \"https://www.virustotal.com");
|
||||
|
||||
if (!uploadUrl)
|
||||
{
|
||||
RaiseUploadError(context, L"Unable to complete the request (no upload URL provided)", 0);
|
||||
goto ExitCleanup;
|
||||
}
|
||||
|
||||
uploadUrl += 41;
|
||||
quote = strchr(uploadUrl, '"');
|
||||
|
||||
if (!quote)
|
||||
{
|
||||
RaiseUploadError(context, L"Unable to complete the request (invalid upload URL)", 0);
|
||||
goto ExitCleanup;
|
||||
}
|
||||
|
||||
objectName = PhCreateStringFromAnsiEx(uploadUrl, quote - uploadUrl);
|
||||
}
|
||||
break;
|
||||
case UPLOAD_SERVICE_JOTTI:
|
||||
{
|
||||
UCHAR hash[20];
|
||||
PPH_STRING hashString;
|
||||
PPH_STRING subObjectName;
|
||||
PSTR id;
|
||||
PSTR quote;
|
||||
|
||||
status = HashFileAndResetPosition(fileHandle, &fileSize64, HASH_SHA1, hash);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
RaiseUploadError(context, L"Unable to hash the file", RtlNtStatusToDosError(status));
|
||||
goto ExitCleanup;
|
||||
}
|
||||
|
||||
hashString = PhBufferToHexString(hash, 20);
|
||||
subObjectName = PhConcatStrings2(L"/nestor/getfileforhash.php?hash=", hashString->Buffer);
|
||||
|
||||
if (!PerformSubRequest(context, serviceInfo->HostName, subObjectName->Buffer, buffer, sizeof(buffer) - 1, &bufferSize))
|
||||
{
|
||||
PhDereferenceObject(hashString);
|
||||
PhDereferenceObject(subObjectName);
|
||||
goto ExitCleanup;
|
||||
}
|
||||
|
||||
PhDereferenceObject(hashString);
|
||||
PhDereferenceObject(subObjectName);
|
||||
|
||||
buffer[bufferSize] = 0;
|
||||
|
||||
if (id = strstr(buffer, "\"id\":"))
|
||||
{
|
||||
id += 6;
|
||||
quote = strchr(id, '"');
|
||||
|
||||
if (quote)
|
||||
{
|
||||
// No upload needed; show the results immediately.
|
||||
context->LaunchCommand = PhFormatString(L"http://virusscan.jotti.org/en/scanresult/%.*S", quote - id, id);
|
||||
SendLaunchCommand(context);
|
||||
goto ExitCleanup;
|
||||
}
|
||||
}
|
||||
|
||||
objectName = PhCreateString(serviceInfo->UploadObjectName);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
objectName = PhCreateString(serviceInfo->UploadObjectName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Create a user agent string.
|
||||
{
|
||||
PPH_STRING phVersion;
|
||||
@@ -262,7 +601,7 @@ static NTSTATUS UploadWorkerThreadStart(
|
||||
connectHandle = InternetConnect(
|
||||
internetHandle,
|
||||
serviceInfo->HostName,
|
||||
80,
|
||||
serviceInfo->HostPort,
|
||||
NULL,
|
||||
NULL,
|
||||
INTERNET_SERVICE_HTTP,
|
||||
@@ -284,11 +623,11 @@ static NTSTATUS UploadWorkerThreadStart(
|
||||
requestHandle = HttpOpenRequest(
|
||||
connectHandle,
|
||||
L"POST",
|
||||
serviceInfo->UploadObjectName,
|
||||
objectName->Buffer,
|
||||
L"HTTP/1.1",
|
||||
L"",
|
||||
acceptTypes,
|
||||
INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_AUTO_REDIRECT,
|
||||
INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_AUTO_REDIRECT | serviceInfo->HostFlags,
|
||||
0
|
||||
);
|
||||
}
|
||||
@@ -426,8 +765,6 @@ static NTSTATUS UploadWorkerThreadStart(
|
||||
// Handle service-specific actions.
|
||||
|
||||
{
|
||||
UCHAR buffer[PAGE_SIZE];
|
||||
ULONG bufferSize;
|
||||
ULONG index;
|
||||
|
||||
bufferSize = sizeof(buffer);
|
||||
@@ -475,7 +812,7 @@ static NTSTATUS UploadWorkerThreadStart(
|
||||
if (hrefEquals)
|
||||
{
|
||||
hrefEquals += 6;
|
||||
quote = strchr(hrefEquals, '\"');
|
||||
quote = strchr(hrefEquals, '"');
|
||||
|
||||
if (quote)
|
||||
{
|
||||
@@ -535,7 +872,7 @@ static NTSTATUS UploadWorkerThreadStart(
|
||||
if (urlEquals)
|
||||
{
|
||||
urlEquals += 4;
|
||||
quote = strchr(urlEquals, '\"');
|
||||
quote = strchr(urlEquals, '"');
|
||||
|
||||
if (quote)
|
||||
{
|
||||
@@ -562,7 +899,7 @@ static NTSTATUS UploadWorkerThreadStart(
|
||||
break;
|
||||
}
|
||||
|
||||
PostMessage(context->WindowHandle, UM_LAUNCH_COMMAND, 0, 0);
|
||||
SendLaunchCommand(context);
|
||||
}
|
||||
|
||||
ExitCleanup:
|
||||
@@ -582,6 +919,8 @@ ExitCleanup:
|
||||
InternetCloseHandle(connectHandle);
|
||||
if (internetHandle)
|
||||
InternetCloseHandle(internetHandle);
|
||||
if (objectName)
|
||||
PhDereferenceObject(objectName);
|
||||
if (fileHandle)
|
||||
NtClose(fileHandle);
|
||||
|
||||
@@ -630,7 +969,9 @@ INT_PTR CALLBACK UploadDlgProc(
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
{
|
||||
PhAcquireQueuedLockExclusive(&context->Lock);
|
||||
context->WindowHandle = NULL;
|
||||
PhReleaseQueuedLockExclusive(&context->Lock);
|
||||
}
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
|
||||
Reference in New Issue
Block a user