Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Suggestion]: My C++ version of the checksum algorithm should it help anyone #13

Open
hashborgir opened this issue Jun 4, 2022 · 3 comments

Comments

@hashborgir
Copy link

hashborgir commented Jun 4, 2022

This is ready to be built in VS2022.

#define _CRT_SECURE_NO_DEPRECATE

#include <iostream>
#include <stdio.h>
#include<string>

using namespace std;

char** argv = NULL;

void main(int argc, char** argv)
{
	if (argv[1] == NULL) {
		cout << "\n\n\tNo .d2s file specified. \n\n\tUsage: d2scs.exe char.d2s\n\n" << endl;
		return;
	}

	FILE* charFile;
	charFile = fopen(argv[1], "r+b");

	// zero out the previous checksum
	char zero[4] = { 0 };
	fseek(charFile, 12, SEEK_SET);
	fwrite(zero, sizeof(char),sizeof(zero), charFile);
	fflush(charFile);
	fseek(charFile, 0, SEEK_SET);

	unsigned char saveFileData[16];
	unsigned long counter = 0;
	unsigned int uSum = 0;

	int n;
	int uVar = 0;
	int byte;

	while ((n = fread(saveFileData, sizeof(char), 16, charFile)) > 0) {
		int i;
		for (i = 0; i < n; i++) {
			// Current byte in charFile		
			byte = (unsigned)saveFileData[i];

			//SAME as uSum  line, just to double check if both produce the same checksum
			if (uVar < 0)
				byte++;
			uVar = byte + uVar * 2;

			//SAME as above block, just to double check if both produce the same checksum
			uSum = ((uSum << 1) | (uSum >> 31)) + (unsigned)saveFileData[i];
		}
		counter += 16;
	}
	
	unsigned long r_uVar = _byteswap_ulong(uVar);
	unsigned long r_uSum = _byteswap_ulong(uSum);

	// write new checksum
	fseek(charFile, 12, SEEK_SET);
	fwrite(&uVar, sizeof(uVar), 1, charFile);
	fflush(charFile);
	fseek(charFile, 0, SEEK_SET);

	printf("\n\n\t%08x checksum written to %s\n\n", r_uVar, argv[1]);

	fclose(charFile);
}
@hashborgir
Copy link
Author

hashborgir commented Jun 4, 2022

Here's the original function located at 6FD269D3 inside D2Game.dll 1.10F

**************************************************************
*                                                            *
*  FUNCTION                                                  *
**************************************************************
uint __fastcall FUN_6fd269d3(byte * param_1, int param_2)
uint              EAX:4          <RETURN>
byte *            ECX:4          param_1
int               EDX:4          param_2
FUN_6fd269d3                                    XREF[1]:     FUN_6fc8a140:6fc8a187(c)  
6fd269d3 85 d2           TEST       param_2,param_2
6fd269d5 75 1b           JNZ        LAB_6fd269f2
6fd269e3 e8 06 5d        CALL       FOG.DLL::Ordinal_10023                           undefined Ordinal_10023()
ff ff
6fd269ed e8 fb 5d        CALL       FUN_6fd1c7ed                                     undefined FUN_6fd1c7ed(UINT para
ff ff
-- Flow Override: CALL_RETURN (CALL_TERMINATOR)
6fd269f3 83 c8 ff        OR         EAX,0xffffffff
LAB_6fd269f7                                    XREF[1]:     6fd26a0d(j)  
6fd269f7 0f b6 31        MOVZX      ESI,byte ptr [param_1]
6fd269fa 0f b6 f8        MOVZX      EDI,AL
6fd269fd 33 f7           XOR        ESI,EDI
6fd269ff c1 e8 08        SHR        EAX,0x8
6fd26a02 8b 34 b5        MOV        ESI,dword ptr [ESI*0x4 + DAT_6fd2a248]
48 a2 d2 6f
6fd26a09 33 c6           XOR        EAX,ESI
6fd26a0b 41              INC        param_1
6fd26a0c 4a              DEC        param_2
6fd26a0d 75 e8           JNZ        LAB_6fd269f7
6fd26a11 f7 d0           NOT        EAX
6fd26a13 c3              RET

@hashborgir
Copy link
Author

hashborgir commented Jun 4, 2022

Here is the original function in C++

uint __fastcall FUN_6fd269d3(byte *param_1,int param_2)

{
  uint uVar1;
  
  if (param_2 == 0) {
    Ordinal_10023(s__dwSize_6fd43f6b + 1,s_C:\projects\D2\head\Diablo2\Sour_6fd43f74,0x40);
                    /* WARNING: Subroutine does not return */
    FUN_6fd1c7ed(0xffffffff);
  }
  uVar1 = 0xffffffff;
  do {
    uVar1 = uVar1 >> 8 ^ *(uint *)(&DAT_6fd2a248 + ((uint)*param_1 ^ uVar1 & 0xff) * 4);
    param_1 = param_1 + 1;
    param_2 = param_2 + -1;
  } while (param_2 != 0);
  return ~uVar1;
}

If you notice there is a certain table whose values are being XOR'd with the checksum. Find the table at 6FD2A248. It's DWORD[256]

DAT_6fd2a248    XREF[1]:     FUN_6fd269d3:6fd26a02(R)  

The values in the table are as follows:

00 => 0X0
01 => 0X77073096
02 => 0XEE0E612C
03 => 0X990951BA
04 => 0X076DC419
05 => 0X706AF48F
06 => 0XE963A535
07 => 0X9E6495A3
08 => 0X0EDB8832
09 => 0X79DCB8A4
0A => 0XE0D5E91E
0B => 0X97D2D988
0C => 0X09B64C2B
0D => 0X7EB17CBD
0E => 0XE7B82D07
0F => 0X90BF1D91
10 => 0X1DB71064
11 => 0X6AB020F2
12 => 0XF3B97148
13 => 0X84BE41DE
14 => 0X1ADAD47D
15 => 0X6DDDE4EB
16 => 0XF4D4B551
17 => 0X83D385C7
18 => 0X136C9856
19 => 0X646BA8C0
1A => 0XFD62F97A
1B => 0X8A65C9EC
1C => 0X14015C4F
1D => 0X63066CD9
1E => 0XFA0F3D63
1F => 0X8D080DF5
20 => 0X3B6E20C8
21 => 0X4C69105E
22 => 0XD56041E4
23 => 0XA2677172
24 => 0X3C03E4D1
25 => 0X4B04D447
26 => 0XD20D85FD
27 => 0XA50AB56B
28 => 0X35B5A8FA
29 => 0X42B2986C
2A => 0XDBBBC9D6
2B => 0XACBCF940
2C => 0X32D86CE3
2D => 0X45DF5C75
2E => 0XDCD60DCF
2F => 0XABD13D59
30 => 0X26D930AC
31 => 0X51DE003A
32 => 0XC8D75180
33 => 0XBFD06116
34 => 0X21B4F4B5
35 => 0X56B3C423
36 => 0XCFBA9599
37 => 0XB8BDA50F
38 => 0X2802B89E
39 => 0X5F058808
3A => 0XC60CD9B2
3B => 0XB10BE924
3C => 0X2F6F7C87
3D => 0X58684C11
3E => 0XC1611DAB
3F => 0XB6662D3D
40 => 0X76DC4190
41 => 0X01DB7106
42 => 0X98D220BC
43 => 0XEFD5102A
44 => 0X71B18589
45 => 0X06B6B51F
46 => 0X9FBFE4A5
47 => 0XE8B8D433
48 => 0X7807C9A2
49 => 0X0F00F934
4A => 0X9609A88E
4B => 0XE10E9818
4C => 0X7F6A0DBB
4D => 0X086D3D2D
4E => 0X91646C97
4F => 0XE6635C01
50 => 0X6B6B51F4
51 => 0X1C6C6162
52 => 0X856530D8
53 => 0XF262004E
54 => 0X6C0695ED
55 => 0X1B01A57B
56 => 0X8208F4C1
57 => 0XF50FC457
58 => 0X65B0D9C6
59 => 0X12B7E950
5A => 0X8BBEB8EA
5B => 0XFCB9887C
5C => 0X62DD1DDF
5D => 0X15DA2D49
5E => 0X8CD37CF3
5F => 0XFBD44C65
60 => 0X4DB26158
61 => 0X3AB551CE
62 => 0XA3BC0074
63 => 0XD4BB30E2
64 => 0X4ADFA541
65 => 0X3DD895D7
66 => 0XA4D1C46D
67 => 0XD3D6F4FB
68 => 0X4369E96A
69 => 0X346ED9FC
6A => 0XAD678846
6B => 0XDA60B8D0
6C => 0X44042D73
6D => 0X33031DE5
6E => 0XAA0A4C5F
6F => 0XDD0D7CC9
70 => 0X5005713C
71 => 0X270241AA
72 => 0XBE0B1010
73 => 0XC90C2086
74 => 0X5768B525
75 => 0X206F85B3
76 => 0XB966D409
77 => 0XCE61E49F
78 => 0X5EDEF90E
79 => 0X29D9C998
7A => 0XB0D09822
7B => 0XC7D7A8B4
7C => 0X59B33D17
7D => 0X2EB40D81
7E => 0XB7BD5C3B
7F => 0XC0BA6CAD
80 => 0XEDB88320
81 => 0X9ABFB3B6
82 => 0X03B6E20C
83 => 0X74B1D29A
84 => 0XEAD54739
85 => 0X9DD277AF
86 => 0X04DB2615
87 => 0X73DC1683
88 => 0XE3630B12
89 => 0X94643B84
8A => 0X0D6D6A3E
8B => 0X7A6A5AA8
8C => 0XE40ECF0B
8D => 0X9309FF9D
8E => 0X0A00AE27
8F => 0X7D079EB1
90 => 0XF00F9344
91 => 0X8708A3D2
92 => 0X1E01F268
93 => 0X6906C2FE
94 => 0XF762575D
95 => 0X806567CB
96 => 0X196C3671
97 => 0X6E6B06E7
98 => 0XFED41B76
99 => 0X89D32BE0
9A => 0X10DA7A5A
9B => 0X67DD4ACC
9C => 0XF9B9DF6F
9D => 0X8EBEEFF9
9E => 0X17B7BE43
9F => 0X60B08ED5
A0 => 0XD6D6A3E8
A1 => 0XA1D1937E
A2 => 0X38D8C2C4
A3 => 0X4FDFF252
A4 => 0XD1BB67F1
A5 => 0XA6BC5767
A6 => 0X3FB506DD
A7 => 0X48B2364B
A8 => 0XD80D2BDA
A9 => 0XAF0A1B4C
AA => 0X36034AF6
AB => 0X41047A60
AC => 0XDF60EFC3
AD => 0XA867DF55
AE => 0X316E8EEF
AF => 0X4669BE79
B0 => 0XCB61B38C
B1 => 0XBC66831A
B2 => 0X256FD2A0
B3 => 0X5268E236
B4 => 0XCC0C7795
B5 => 0XBB0B4703
B6 => 0X220216B9
B7 => 0X5505262F
B8 => 0XC5BA3BBE
B9 => 0XB2BD0B28
BA => 0X2BB45A92
BB => 0X5CB36A04
BC => 0XC2D7FFA7
BD => 0XB5D0CF31
BE => 0X2CD99E8B
BF => 0X5BDEAE1D
C0 => 0X9B64C2B0
C1 => 0XEC63F226
C2 => 0X756AA39C
C3 => 0X026D930A
C4 => 0X9C0906A9
C5 => 0XEB0E363F
C6 => 0X72076785
C7 => 0X05005713
C8 => 0X95BF4A82
C9 => 0XE2B87A14
CA => 0X7BB12BAE
CB => 0X0CB61B38
CC => 0X92D28E9B
CD => 0XE5D5BE0D
CE => 0X7CDCEFB7
CF => 0X0BDBDF21
D0 => 0X86D3D2D4
D1 => 0XF1D4E242
D2 => 0X68DDB3F8
D3 => 0X1FDA836E
D4 => 0X81BE16CD
D5 => 0XF6B9265B
D6 => 0X6FB077E1
D7 => 0X18B74777
D8 => 0X88085AE6
D9 => 0XFF0F6A70
DA => 0X66063BCA
DB => 0X11010B5C
DC => 0X8F659EFF
DD => 0XF862AE69
DE => 0X616BFFD3
DF => 0X166CCF45
E0 => 0XA00AE278
E1 => 0XD70DD2EE
E2 => 0X4E048354
E3 => 0X3903B3C2
E4 => 0XA7672661
E5 => 0XD06016F7
E6 => 0X4969474D
E7 => 0X3E6E77DB
E8 => 0XAED16A4A
E9 => 0XD9D65ADC
EA => 0X40DF0B66
EB => 0X37D83BF0
EC => 0XA9BCAE53
ED => 0XDEBB9EC5
EE => 0X47B2CF7F
EF => 0X30B5FFE9
F0 => 0XBDBDF21C
F1 => 0XCABAC28A
F2 => 0X53B39330
F3 => 0X24B4A3A6
F4 => 0XBAD03605
F5 => 0XCDD70693
F6 => 0X54DE5729
F7 => 0X23D967BF
F8 => 0XB3667A2E
F9 => 0XC4614AB8
FA => 0X5D681B02
FB => 0X2A6F2B94
FC => 0XB40BBE37
FD => 0XC30C8EA1
FE => 0X5A05DF1B
FF => 0X2D02EF8D

@hashborgir
Copy link
Author

You can either use the XOR Table and XOR the value of every byte or you can use the algorithm in the previous post.

uVar1 = uVar1 >> 8 ^ DWORD_ARRAY_6fd2a248[(uint)*param_1 ^ uVar1 & 0xff];

@hashborgir hashborgir changed the title C++ version of the D2S Checksum Calculator Should it help someone. [SUGGESTION] My C++ version of the D2S Checksum Calculator Should it help someone. Jun 4, 2022
@hashborgir hashborgir changed the title [SUGGESTION] My C++ version of the D2S Checksum Calculator Should it help someone. [Suggestion]: My C++ version of the checksum algorithm should it help anyone Jun 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant