Log in

View Full Version : CRC32b


markh51
October 3rd, 2005, 11:45
Does anyone know anything about this algorithm ?

I had a search though google for a utility which would work out a files CRC32b value but couldn't find anything.

Cheers guys.

naides
October 3rd, 2005, 13:51
www.softuarium.com/downloads.php

That was the third hit in a Google search
OR
You need to elaborate a little on exactly what you are trying to do with CRC32B

markh51
October 3rd, 2005, 14:16
That program appears to be the only thing what has anything to do with CRC32b. It does not support CRC32b in the 'evaluation' version.

I need to be able to work out the CRC value of a given file using the CRC32b algorithm.

I came across some source code but get some errors while trying to compile it. (ERR: unresolved external symbol _WinMain@16)
Code:
#include <stdio.h>

unsigned long getcrc();

unsigned long crcTable[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};

main(argc, argv)
int argc;
char *argv[];
{
int i;
FILE *fp;
unsigned long crc;

if (argc < 2) {
crc = getcrc( stdin );
printf("crc32b = %08lx for <stdin>\n", crc);
} else {
for (i=1; i<argc; i++) {
if ( (fp=fopen(argv[I],"rb") == NULL ) {
printf("error opening file \"%s\"!\n",argv[I]);
} else {
crc = getcrc( fp );
printf("crc32b = %08lx for \"%s\"\n",
crc, argv[I]);
fclose( fp );
}
}
}
}

unsigned long getcrc(fp)
FILE *fp;
{
register unsigned long crc;
int c;

crc = 0xFFFFFFFF;
while( (c=getc(fp)) != EOF ) {
crc = ((crc>>8) & 0x00FFFFFF) ^ crcTable[ (crc^c) & 0xFF ];
}
return( crc^0xFFFFFFFF );
}

Neitsa
October 3rd, 2005, 16:39
Hello,

Quote:

(ERR: unresolved external symbol _WinMain@16)


You're trying to compile this program as a "windows" program, but you should compile it as a console program.

In the ISO norme of C, "main" always return an integer type. Here are some prototypes of main func. :

Code:

int main(void);

or

int main(int argc, char * argv[]);

int main () ;//OK in C++ but not in C


That's just some not so important points, even if your compiler will compil it correctly, some compilers may issue a warning or complain about an error...(and some C gurus may flame you, that was my case , Iv' been flamed many times for my bad coding style...).

markh51
October 3rd, 2005, 17:32
It compiles fine as a console application. Thanks.

What parameters should be entered when running the program from the prompt ? I've tried the file name after the program name but just get "Error opening file...", even though the file is in the same directory.

Neitsa
October 3rd, 2005, 18:53
You must provide a complete path and avoid filepath with space in it. I've never really understood why argv (or at least the loader) can't handle those spaces...


E:\AppData\Visual C++\CRC32b\Release>CRC32b.exe C:\boot.ini
crc32b = bad83f38 for "C:\boot.ini"

it works

markh51
October 4th, 2005, 04:08
Yipp that works OK...

One problem though, the program which uses the CRC32b to check to see if the files have been modifed comes out with different values from the above code for the same file. I used PEiD which identified the algorithm as CRC32b, but it must be modified somehow.

Can I post the code for one of you experts to look at ?

naides
October 4th, 2005, 12:11
Actually depending on minor details, specifically in the poly(nomial) or the details in the implmentation, you could construct your own personal CRC32, which would not be of much use for a widely applied hashing validation, because the other person needs to use exactly the same (modified) algorithm during validation stage.
What you are against seems that: a peculiar implementation of CRC or perhaps another hashing function, to detect code tampering for protection purposes. What you may need to do is reverse the actual algo used by your target and implement yourself a modified version. If it is indeed CRC, pay close attention to the polynomial table that your code may be using, to what is the intial state of the CRC (By default FFFFFFFF but could be anything) and if the final CRC gets xored with some number.

PeID may not be the best tool to detect the hashing function.

Also, search in the board: A while back, mike posted some info about the typical 'signatures' of several crypto functions.

markh51
October 4th, 2005, 12:22
Well I'm far from an expert on the matters of crypto and algorithms !

I need to be able to recreate this algorithm so I can use it in my utility to generate these CRC values.

This is the code which creates the value:
Code:

.text:00401000 var_314 = byte ptr -314h
.text:00401000 var_310 = byte ptr -310h
.text:00401000 var_210 = byte ptr -210h
.text:00401000 var_110 = dword ptr -110h
.text:00401000 var_10C = dword ptr -10Ch
.text:00401000 var_108 = dword ptr -108h
.text:00401000 var_104 = dword ptr -104h
.text:00401000 var_100 = byte ptr -100h
.text:00401000 arg_0 = dword ptr 8
.text:00401000 arg_4 = dword ptr 0Ch
.text:00401000
.text:00401000 push ebp
.text:00401001 mov ebp, esp
.text:00401003 sub esp, 314h
.text:00401009 mov [ebp+var_104], 0
.text:00401013 mov word ptr [ebp+var_110], 0
.text:0040101C lea eax, [ebp+var_210]
.text:00401022 push eax ; char *
.text:00401023 lea ecx, [ebp+var_100]
.text:00401029 push ecx ; char *
.text:0040102A lea edx, [ebp+var_310]
.text:00401030 push edx ; char *
.text:00401031 lea eax, [ebp+var_314]
.text:00401037 push eax ; char *
.text:00401038 mov ecx, [ebp+arg_0]
.text:0040103B push ecx ; char *
.text:0040103C call __splitpath
.text:00401041 add esp, 14h
.text:00401044 push offset unk_40D630
.text:00401049 mov edx, [ebp+arg_0]
.text:0040104C push edx
.text:0040104D call _fopen
.text:00401052 add esp, 8
.text:00401055 mov [ebp+var_108], eax
.text:0040105B cmp [ebp+var_108], 0
.text:00401062 jnz short loc_401068
.text:00401064 xor eax, eax
.text:00401066 jmp short loc_4010E3
.text:00401068 ; ---------------------------------------------------------------------------
.text:00401068
.text:00401068 loc_401068: ; CODE XREF: sub_401000+62j
.text:00401068 mov eax, [ebp+var_110]
.text:0040106E and eax, 0FFFFh
.text:00401073 mov [ebp+var_104], eax
.text:00401079
.text:00401079 loc_401079: ; CODE XREF: sub_401000+C2j
.text:00401079 mov ecx, [ebp+var_108]
.text:0040107F push ecx
.text:00401080 call _getc
.text:00401085 add esp, 4
.text:00401088 mov [ebp+var_10C], eax
.text:0040108E mov edx, [ebp+var_104]
.text:00401094 shr edx, 18h
.text:00401097 xor edx, [ebp+var_10C]
.text:0040109D and edx, 0FFh
.text:004010A3 mov eax, [ebp+var_104]
.text:004010A9 shl eax, 8
.text:004010AC mov ecx, dword_40D230[edx*4]
.text:004010B3 xor ecx, eax
.text:004010B5 mov [ebp+var_104], ecx
.text:004010BB cmp [ebp+var_10C], 0FFFFFFFFh
.text:004010C2 jnz short loc_401079
.text:004010C4 mov edx, [ebp+var_108]
.text:004010CA push edx
.text:004010CB call _fclose
.text:004010D0 add esp, 4
.text:004010D3 mov eax, [ebp+arg_4]
.text:004010D6 mov ecx, [ebp+var_104]
.text:004010DC mov [eax], ecx
.text:004010DE mov eax, 1
.text:004010E3
.text:004010E3 loc_4010E3: ; CODE XREF: sub_401000+66j
.text:004010E3 mov esp, ebp
.text:004010E5 pop ebp
.text:004010E6 retn
.text:004010E6 sub_401000 endp

bilbo
October 5th, 2005, 07:10
The original C source could have been like this:
Code:

#include <stdio.h>
#include <stdlib.h>

unsigned crctable[256]; // don't forget to initialize from dword_40d230

/*
* will return 1(ok)/0(ko)
*/
int
crc(char *filename/*arg_0*/, unsigned *presult/*arg_4*/)
{
// locals
unsigned total; // var_104
unsigned short initialvalue = 0; // var_110
unsigned currentchar; // var_10C
FILE *hfile; // var_108

char drive[4], // var_314
dir[0x100], // var_310,
fname[0x100], // var_100
ext[0x100]; // var_210

_splitpath(filename, drive, dir, fname, ext); // useless!!!

hfile = fopen(filename, "rb"/*unk_40D630, I guess!*/);
if (hfile == 0) return 0;

total = initialvalue;
do {
currentchar = getc(hfile);

total = total<<8 ^ crctable[(unsigned char)(total>>24 ^ currentchar)];
}
while (currentchar != EOF);

fclose(hfile);
*presult = total;
return 1;
}

void
main(int argc, char **argv)
{
unsigned result;

if (argc != 2) {
printf("usage: %s filename\n", argv[0]);
return;
}

if (!crc(argv[1], &result)) printf("ko!\n";
else printf("result is %#x\n", result);
}

but I have not tested it...

By the way, you could also "rip" the whole subroutine as it is...
Regards, bilbo

markh51
October 5th, 2005, 07:37
Quote:
don't forget to initialize from dword_40d230


Not sure what you mean

What the utility is supposed to do is take a directory (i.e D:\Data) then loop through all the files and sub directories within the given path and output the CRC result to a file like:

a1234567 \data\subdir\file1.exe
b1234567 \data\subdir\file.dll

that why I suppose the original code used:
_splitpath(filename, drive, dir, fname, ext); ?

You code works but does't produce the same results as the original. Does it have something to do with the codes for the crcTable ?

bilbo
October 5th, 2005, 09:48
Quote:
[Originally Posted by markh51]What the utility is supposed to do is take a directory (i.e D:\Data) then loop through all the files and sub directories within the given path and output the CRC result to a file like:

a1234567 \data\subdir\file1.exe
b1234567 \data\subdir\file.dll

that why I suppose the original code used:
_splitpath(filename, drive, dir, fname, ext); ?

Let's see!
_splitpath() has its prototype in stdio.h, and its first argument is defined as
Code:
const char *filename
This means that "filename" will not be changed inside the function.
Now since as first argument to _splitpath() is passed arg_0, and arg_0 is reused in the following operations (discarding drive, dir, fname and ext), I assert that _splitpath() is useless!
If you want to check yourself my assertion, please put a breakpoint at address 40103B and write down the address in ECX (arg_0): the string at that address will be a filename, not a directory. Next execute the call, and you will see that the address contents is not changed.
This means that the recursion over a directory must be performed by the caller of the routine under discussion, and that _splitpath() is useless!

Quote:
[Originally Posted by bilbo]don't forget to initialize from dword_40d230
Have a look at line
Code:
.text:004010AC mov ecx, dword_40D230[edx*4]

This means: move in ECX the long found at address 40D230 + EDX*4
In our C translation: move in register ECX the value of the element crctable[EDX] (where *4 is implicit in the size of the elements)

Obviously crctable must have been initialized with the same values found in area 40D230 - 40D630 (40D230+100*4, in hex)!
Use the usual syntax:
Code:
unsigned crctable[0x100] = { <long at 40D230>, <long at 40D234>, ..., <long at 40D62C> };


Tip: use HexWorkshop for cutting and pasting the table.

Regards, bilbo

markh51
October 5th, 2005, 10:00
How would I mod the code so that is does what I need ?

Quote:
What the utility is supposed to do is take a directory (i.e D:\Data) then loop through all the files and sub directories within the given path and output the CRC result to a file like:

a1234567 \data\subdir\file1.exe
b1234567 \data\subdir\file.dll


Also where do I paste the table once I have cut it from hex workshop ?

Sorry for being dim, but I'm not quite a guru yet

bilbo
October 6th, 2005, 03:01
QUESTION 1 - Call the subroutine crc() from main() in a loop, building each filename with the functions _findfirst, _findnext, _findclose

QUESTION 2 - Use HexWorkshop 4.23. Before copying:
Select Tab Options->Preferences->Import/Export->C source Format
and set Data type: 32bits, Swap Byte Order selected, Default variable name: crctable.
Then select the memory (400h bytes) dragging the mouse with the left button clicked.
Then click Edit->Copy As->C Source
Finally paste (Control-V) in your text editor, into the C source file.

Phew! Now you must be a guru
Regards, bilbo

markh51
October 6th, 2005, 03:29
Cheers Bilbo, you're a genius

Don't suppose you can quickly mode your code to do what I need in question 1 ? I can't work it out

bilbo
October 6th, 2005, 04:39
Quote:
Cheers Bilbo, you're a genius

I am a hobbit - LOL

Quote:
Don't suppose you can quickly mode your code to do what I need in question 1 ? I can't work it out
I suppose you can quickly google for
Code:
_findfirst _findnext _findclose "directory contents"


Regards, bilbo

markh51
October 6th, 2005, 14:30
I had a peek on Goolge and got a few hit's but I wouldn't know where to start with this code

bilbo
October 7th, 2005, 03:26
Here is a program to print all the files in directories and subdirectories:
Code:

/* coded by bilbo - 07oct05 */

#include <io.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

void
listDir(char *path)
{
struct _finddata_t fileInfo;
long fPtr;
char filespec[512], fullname[512];

strcpy(filespec, path);
// append the trailing backslash if not already there
if (path[strlen(path)-1] != '\\') strcat(filespec, "\\";
strcat(filespec, "*";

if ((fPtr = _findfirst(filespec, &fileInfo)) == -1) return;

do {
strcpy(fullname, filespec);
// remove the trailing '*'
fullname[strlen(fullname)-1] = 0;
strcat(fullname, fileInfo.name);

// skip entries '.' and '..'
if (fullname[strlen(fullname)-1] == '.') continue;
// subdirectory recursion
if (fileInfo.attrib&_A_SUBDIR) listDir(fullname);
// one regular file found
else printf("%s\n", fullname);
}
while (_findnext(fPtr, &fileInfo) == 0);

_findclose(fPtr);
}

void
main(int argc, char *argv[])
{
if (argc != 2) printf("usage: %s dirname\n", argv[0]);
else listDir(argv[1]);
}



Just a little homework for you:
replace
Code:
printf("%s\n", fullname)
with a call to
Code:
crc(fullname, &result)

and you are done!

Regards, bilbo

markh51
October 7th, 2005, 04:53
Thanks bilbo, I will give it a try later.

If it works... you're a star

Cheers mate

JMI
October 7th, 2005, 10:37
He' not a "star," he's a Hobbit.

He's just well traveled through Middle Earth and has made many useful discoveries and read many arcane texts and ancient scripts along the way.

Regards,

JMI
October 9th, 2005, 21:53
Small problem with database updating has caused the loss of a couple of Posts in this Thread. dELTA complainted about markh51 not doing his own basic research; i suggested we went markh51 to a Hobbit run school ; and markh51 complained he only wanted someone to tell him WHAT to look for, not give him the answer. Whew. That's shorter and sweeter.

Regards,

dELTA
October 10th, 2005, 08:10
Ok, markh51, if you really just want to know what to look for, here it is, and it should be more than enough:

GetFileAttributes