Code: Select all
{ Game : helldivers2.exe
Version:
Date : 2024-04-30
Author : ZoDDeL
Mod by : Anton v5
Tested on: .304 path
If hold CHEAT_ALL_HOTKEY while taking sample it will override all 3 counters to specified (edit section)
If take sample and dont hold CHEAT_ALL_HOTKEY you receive HOTKEY_NOT_PRESSED_ADD_VALUE of sample type you taken
You can edit #define section values below
For debugging purposes you can open DebugViewPP tool and take some samples. you will receive messages.
}
{$c}
// YOU CAN EDIT SECTION START
#define CHEAT_ALL_HOTKEY 'C' // take sample while holding it and you will get what you set
// Keep common + rare + super sum below or equal to 100. For example you can specify 50+40+10 = 100
#define HOTKEY_PRESSED_COMMON_SAMPLE_COUNT_REDEFINE 45
#define HOTKEY_PRESSED_RARE_SAMPLE_COUNT_REDEFINE 30
#define HOTKEY_PRESSED_SUPER_SAMPLE_COUNT_REDEFINE 10
// if hotkey is not pressed and player take sample it will add specified value (game default is 1)
#define HOTKEY_NOT_PRESSED_ADD_VALUE 10
#define SECRET_HOTKEY 'Q' // if take sample while holding this, you will receive +1 samples (no cheat mode)
// YOU CAN EDIT SECTION END
#define NO_OLDNAMES
#include <windows.h>
extern __cdecl int sprintf(char *, char *, ...);
extern __cdecl void OutputDebugStringA(const char* lpOutputString);
short GetAsyncKeyState(int);
char debug_string[400];
typedef struct {
int common;
int rare;
int super;
} Samples;
int *SAMPLES_COMMON;
int *SAMPLES_RARE;
int *SAMPLES_SUPER;
void show_bits_sprintf(int *rdx_value, char *buffer) {
unsigned int mask = 0x80000000; // Маска для старшего бита
int i;
for (i = 0; i < 32; ++i) {
// Проверяем, установлен ли бит
if (*rdx_value & mask) {
sprintf(buffer + i, "1");
} else {
sprintf(buffer + i, "0");
}
mask >>= 1; // Сдвигаем маску на один бит вправо
}
sprintf(buffer + 32, "\0"); // Добавляем завершающий нуль-символ
}
{$asm}
[ENABLE]
aobscanmodule(samples_inject,game.dll,48 8D 14 41 48 8B 43 40 4B 8D 0C 89 44 01 7C 90 04) // should be unique
alloc(samples_newmem,$2000)
label(samples_return)
samples_newmem:
// original code start
lea rdx,[rcx+rax*2]
mov rax,[rbx+40]
lea rcx,[r9+r9*4]
// add [rax+rdx*4+04],r15d
// original code end
/*
cmp rdx,0
je samples_common
cmp rdx,1
je samples_rare
cmp rdx,2
je samples_super
samples_common: // when you pickup common
mov [rax+rdx*4+04],#49 // common sample
mov [rax+rdx*4+04+4],#30 // rare sample
mov [rax+rdx*4+04+8],#20 // super sample
jmp samples_return
samples_rare: // when you pickup rare
mov [rax+rdx*4+04-4],#49 // common sample
mov [rax+rdx*4+04],#30 // rare sample
mov [rax+rdx*4+04+4],#20 // super sample
jmp samples_return
samples_super: // when you pickup super
mov [rax+rdx*4+04-8],#49 // common sample
mov [rax+rdx*4+04-4],#30 // rare sample
mov [rax+rdx*4+04],#20 // super sample
jmp samples_return
*/
{$ccode base1=rax rdx=rdx}
// calculate base_address of samples structure
// rdx 0 = base+4
// rdx 1 = base+4+4-4 = base+4
// rdx 2 = base+8+4-8 = base+4
// Samples* samples = (Samples*)(base1 + sample_type*4 + 4 - sample_type*4 );
short sample_type = rdx % 10; // for common samples can be 0 20 or 60 (zero at the end). Rare 1 or 21. Super 2 or 22
short sample_unk = (int)(rdx / 10);
int *picked_up_sample_counter = (int*)(base1 + rdx*4 + 4);
//Samples* samples = (Samples*)(base1 + 4);
Samples* samples = (Samples*)(base1 + rdx*4 + 4 - sample_type*4);
SAMPLES_COMMON = &samples->common;
SAMPLES_RARE = &samples->rare;
SAMPLES_SUPER = &samples->super;
int samples_count_now = samples->common + samples->rare + samples->super;
sprintf(debug_string, "Samples: Taken type: %d | counts %d + %d + %d = %d. Unknown value is %d", sample_type, samples->common, samples->rare, samples->super, samples_count_now, sample_unk);
OutputDebugStringA(debug_string);
/*
OutputDebugStringA("Samples: sample_type RDX bits:");
show_bits_sprintf(&sample_type, &debug_string);
OutputDebugStringA(debug_string);
*/
/*
OutputDebugStringA("Samples: sample amount r15d bits:");
show_bits_sprintf(&taken_sample_amount_r15d, &debug_string);
OutputDebugStringA(debug_string);
*/
// Already more than maxed out, restore max counts and exit
if (samples_count_now > 100) {
samples->common = HOTKEY_PRESSED_COMMON_SAMPLE_COUNT_REDEFINE;
samples->rare = HOTKEY_PRESSED_RARE_SAMPLE_COUNT_REDEFINE;
samples->super = HOTKEY_PRESSED_SUPER_SAMPLE_COUNT_REDEFINE;
sprintf(debug_string, "Samples: count is >100. Restoring to maximum: %d %d %d", samples->common, samples->rare, samples->super);
OutputDebugStringA(debug_string);
goto end_section;
}
// Max all if hotkey pressed
if (GetAsyncKeyState(CHEAT_ALL_HOTKEY) & 0x8000) {
samples->common = HOTKEY_PRESSED_COMMON_SAMPLE_COUNT_REDEFINE;
samples->rare = HOTKEY_PRESSED_RARE_SAMPLE_COUNT_REDEFINE;
samples->super = HOTKEY_PRESSED_SUPER_SAMPLE_COUNT_REDEFINE;
sprintf(debug_string, "Samples: hotkey pressed. Sample counts just set to maximum: %d %d %d", samples->common, samples->rare, samples->super);
OutputDebugStringA(debug_string);
goto end_section;
}
int value_to_add = 1;
if (GetAsyncKeyState(SECRET_HOTKEY) & 0x8000) {
sprintf(debug_string, "Samples: secret hotkey pressed. Samples piclup will be default(1)");
OutputDebugStringA(debug_string);
} else {
value_to_add = HOTKEY_NOT_PRESSED_ADD_VALUE;
int add_limit = 100 - samples_count_now;
if (add_limit == 0) {
sprintf(debug_string, "Samples: limit reached %d. No additional samples will be added", add_limit);
OutputDebugStringA(debug_string);
} else if (add_limit < 0) {
samples->common = 50;
samples->rare = 40;
samples->super = 10;
sprintf(debug_string, "Samples: count is more than allowed: %d. No additional samples will be added. Sample counts are set to maximum: %d %d %d", samples_count_now, samples->common, samples->rare, samples->super);
OutputDebugStringA(debug_string);
} else if (value_to_add > add_limit) {
value_to_add = add_limit;
sprintf(debug_string, "Samples: too much samples already collected. Add value is clamped to %d/%d", value_to_add, HOTKEY_NOT_PRESSED_ADD_VALUE);
OutputDebugStringA(debug_string);
} else {
sprintf(debug_string, "Samples: will add %d of type %d", value_to_add, sample_type);
OutputDebugStringA(debug_string);
}
}
*picked_up_sample_counter += value_to_add;
/*
if (sample_type == 0) {
samples->common += value_to_add;
}
if (sample_type == 1) {
samples->rare += value_to_add;
}
if (sample_type == 2) {
samples->super += value_to_add;
}
*/
/*
samples->common += value_to_add+1;
samples->rare += value_to_add+2;
samples->super += value_to_add+3;
*/
/*
// hardcoded limit guard
samples_count_now = samples->common + samples->rare + samples->super;
if (samples_count_now > 100) {
samples->common = 50;
samples->rare = 40;
samples->super = 10;
sprintf(debug_string, "Samples: Hardcoded guard. Samples SUM is >100: %d. Sample counts are reset to maximum allowed: %d %d %d", samples_count_now, samples->common, samples->rare, samples->super);
OutputDebugStringA(debug_string);
}
*/
/*
// output debug. you can look in DebugViewPP tool https://github.com/CobaltFusion/DebugViewPP
sprintf(debug_string, "Samples out: common %d | rare %d | super %d", samples->common, samples->rare, samples->super);
OutputDebugStringA(debug_string);
*/
end_section:
{$asm}
jmp samples_return
samples_inject:
jmp far samples_newmem
nop 3
samples_return:
registersymbol(samples_inject)
[DISABLE]
samples_inject:
db 48 8D 14 41 48 8B 43 40 4B 8D 0C 89 44 01 7C 90 04
unregistersymbol(samples_inject)
dealloc(samples_newmem)
{
// ORIGINAL CODE - INJECTION POINT: game.dll+608B8F
game.dll+608B68: 41 FF C0 - inc r8d
game.dll+608B6B: 45 3B C1 - cmp r8d,r9d
game.dll+608B6E: 72 E0 - jb game.dll+608B50
game.dll+608B70: B8 FF FF FF FF - mov eax,FFFFFFFF
game.dll+608B75: 48 8B 74 24 48 - mov rsi,[rsp+48]
game.dll+608B7A: 48 8B 6C 24 40 - mov rbp,[rsp+40]
game.dll+608B7F: 48 8B 7C 24 50 - mov rdi,[rsp+50]
game.dll+608B84: 44 8B C8 - mov r9d,eax
game.dll+608B87: 41 8D 4E FF - lea ecx,[r14-01]
game.dll+608B8B: 4B 8D 04 89 - lea rax,[r9+r9*4]
// ---------- INJECTING HERE ----------
game.dll+608B8F: 48 8D 14 41 - lea rdx,[rcx+rax*2]
// ---------- DONE INJECTING ----------
game.dll+608B93: 48 8B 43 40 - mov rax,[rbx+40]
game.dll+608B97: 4B 8D 0C 89 - lea rcx,[r9+r9*4]
game.dll+608B9B: 44 01 7C 90 04 - add [rax+rdx*4+04],r15d
game.dll+608BA0: BA 94 4C 74 92 - mov edx,92744C94
game.dll+608BA5: 48 8B 43 40 - mov rax,[rbx+40]
game.dll+608BA9: 4C 8D 04 C8 - lea r8,[rax+rcx*8]
game.dll+608BAD: 48 8B 43 30 - mov rax,[rbx+30]
game.dll+608BB1: 4A 8B 0C C8 - mov rcx,[rax+r9*8]
game.dll+608BB5: 8B 49 10 - mov ecx,[rcx+10]
game.dll+608BB8: E8 63 13 49 00 - call game.dll+A99F20
}