Access voilation exception when trying to rewrite jmp - c++

I have a game, I disasembled it and located a jump which I want to rewrite,
but whenever I try to write to the address I get a access voilation exception, even when I use VirtualProtect and set the READWRITE permission.
the instruction on 0x0042BD5F is this:
0x0046AACF E9 FF FF 89 FC | jmp some address here
Now, when I try to write to 0x0042BD5F, to change the relative jump address, I get an access voilation exception.
How do I change the jump on that address?
Code was requested, so here it is:
#define AddVar(Type,Name,Address) Type& Name = *reinterpret_cast<Type*>(Address)
/*
Hooker
1b 0x0042BD5F == E9 <relative jmp>
4b 0x0042BD60 - relative jump offset (always the value 0xFFFF89FC)
*/
AddVar(uqbyte, jump_hook_bytes, 0x0042BD60);
//the user tick function
void(*tick)(void);
void SetTick(void(*passed)(void))
{
tick = passed;
}
void Ticker();
void OnDLLLoad(void(*passed)(void) = nullptr)
{
tick = passed;
//point the game loop end to Ticker()
//replace the jump address
//jmp (DESTINATION_RVA - CURRENT_RVA - 5 [sizeof(E9 xx xx xx xx)])
DWORD old;
VirtualProtect(
(LPVOID)0x0042BD5F,
0x05,
PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE,
&old
);
jump_hook_bytes = (((uqbyte)((uqbyte*)&Ticker) - (uqbyte)0x0042BD5F) - (uqbyte)0x0000005);
}
void Ticker()
{
if (tick != nullptr)
{
tick();
}
__asm
{
MOV EAX, 0x0042B9EA;//old address
JMP EAX;
}
}
uqbyte is an unsigned long.
When calling getlasterror the code seems to return the decimal error 87 (INVALID_PARAMETERS).

The documentation for the memory protection constants says:
The following are the memory-protection options; you must specify one of the following values when allocating or protecting a page in memory.
It then lists a number of values, including the three that you combined together. When the documentation says "specify one of the following values" it means exactly one. You must not combine them.
You need to use PAGE_EXECUTE_READWRITE on its own.
I recommend that you add error checking around all your API calls. I also think that you could avoid hard coding the addresses.

You need to use a debugger or a program that enables the process token privilege for debugger mode (like a trainer). I assume this isn't being used for an online cheat (offline shouldn't matter).

Passing PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE is wrong, you need to pass PAGE_EXECUTE_READWRITE only to Virtual Protect. Now it works.

Related

What's the best way to parse a packet data in c++?

I'm transcoding a Delphi App to C++ and got a problem to get the correct way to do the cases of packet headers in C++.
The Headers Comes as "Dword" in a UCHAR buf and i dont want make like: if (packet[0] == 0xFF && packet[1] == 0xFF...);
Ex: Delphi Working with switch case:
case PDword(#Packet[6])^ of
$68FB0200:
begin
//Dword match correctly
End;
end;
is there a way to do the same in C++ like the Delphi Example?
Already checked for some methds but ever fails the comparsion.
UCHAR *Packet ;
Packet = ParsePacket(buf->Buf, buf->Size);
// The ParsePacket Returns FB 00 00 00 78 00 01 F3 02 FD
DWORD Op1 = 0x01F302FD;
DWORD *p_dw = (DWORD*) Packet[6];
if (p_dw == Op1)
{
//Dword never match...
}
Yes, the portable C (and C++) way is:
DWORD const Op1 = 0x01F302FD;
if (0 == memcmp(Packet + 6, &Op1, sizeof Op1)) { ... }
Note that we haven't tried to access the bytes at Packet+6 as a 32-bit quantity... they're likely to be misaligned for that. We're just asking whether the same sequence of 4 bytes exists there as exist in Op1.
The obvious issue with DWORD *p_dw = (DWORD*) Packet[6] is that you take a value as an address. You probably meant DWORD *p_dw = (DWORD*)&(Packet[6]).
Note, however, that you get additional troubles for two reasons:
First, alignment could be wrong such that the pointer received is not a valid address to be taken for dereferencing a DWORD. This is undefined behaviour then.
Second, you depend on a specific endianess.
To overcome the first issue, you could use memcpy:
DWORD Op2 = 0;
memcpy(&Op2,Packet+6,sizeof(Op2));
To overcome both the first and the second issue, you'll need to sum the bytes on your own, e.g.:
DWORD Op2 = Packet[6]<<24 | Packet[7]<<16 | Packet[8]<<8 | Packet[9]

Write jump to memory

I'm trying to write a jump to memory, and I can't seem to find anywhere which can explain me how it works.
typedef UINT(WINAPI* tResetWriteWatch)(LPVOID lpBaseAddress, SIZE_T dwRegionSize);
UINT WINAPI ResetWriteWatchHook(LPVOID lpBaseAddress, SIZE_T dwRegionSize){
printf("Function called\n");
return 0;
}
void main(){
DWORD64 hookAddr = (DWORD64)&ResetWriteWatch;
WriteJump(hookAddr, ResetWriteWatchHook/*Let's say it's 0x7FE12345678*/);//Writes E9 XX XX XX XX to memory
}
My main issue is that I don't understand: how do I convert asm JMP 0x7FE12345678 to E9 XX XX XX XX so I can write it at hookAddr.
Process is 64 bits.
This is how it's commonly done on a 32bit program (not sure how much is different on 64 bit), but this should give you an idea on where to go. This is specific to windows because of VirtualProtect, but you can use mprotect if you are on linux.
#include <stdio.h>
#include <windows.h>
void foo() {
printf("Foo!");
}
void my_foo() {
printf("My foo!");
}
int setJMP(void *from, void *to) {
DWORD protection;
if (!VirtualProtect(from, 5, PAGE_EXECUTE_READWRITE, &protection)) { // We must be able to write to it (don't necessarily need execute and read)
return 0;
}
*(char *)from = 0xE9; // jmp opcode
*(int *)(from + 1) = (int)(to - from - 5); // relative addr
return VirtualProtect(from, 5, protection, &protection); // Restore original protection
}
int main() {
setJMP(foo, my_foo);
foo(); // outputs "My foo!"
return 0;
}
I would suggest using an assembler to generate the correct bytes. Simply create the following file and run it through NASM:
BITS 64
JUMP 0x7fe1234
The result is:
2f e9 fe 12 00 07 (due to the LE byte order). This is a relative jump, so it will be hard to generate from high level code. You might want to use the opcode EA instead, which performs an absolute jump. Then you can simply use the absolute address of the location to which you want to jump.

Assembly code causes recursion

I've been writing a C application, and I came in need of x86 assembly language. I'm pretty new to assembly, and the following snippet causes recursion:
unsigned int originalBP;
unsigned fAddress;
void f(unsigned short aa) {
printf("Function %d\n", aa);
}
unsigned short xx = 77;
void redirect() {
asm {
pop originalBP
mov fAddress, offset f
push word ptr xx
push fAddress
push originalBP
}
}
If i call redirect , it will repeatedly output: "Function 1135"
First, here are a few information about the environment in which this code is executed:
This code is written to be executed under NTVDM
Tiny memory model is used ( all segment pointer registers point to the same segment )
Here's my expectation of what the code above should do ( this is most likely the culprit of the error ) :
Pop the stack and store value in originalBP; I believe the value is actually the address of the current function i.e. redirect
Push f's argument value ( value of xx ) to the stack
Push address of f to stack ( since there's only one segment, only offset is needed )
Push back the address of redirect
Of course, if this were the correct flow, recursion would be apparent ( except the part where 1135 is printed instead of 7). But interestingly, doing the same with a function with no arguments produces only one line of output i.e.:
unsigned int originalBP;
unsigned fAddress;
void f() {
printf("Function");
}
void redirect() {
asm {
pop originalBP
mov fAddress, offset f
push fAddress
push originalBP
}
}
This probably means that my understanding of the above code is completely wrong. What is the real issue in this code?
EDIT: I probably left some of the things unsaid:
This is a 16 bit application
Compiler used is Borland C++ 3.1, as Eclipse plugin
redirect is called from main as redirect()
EDIT (regarding Margaret Bloom's answer) Here's an example of instruction execution once redirect is called. Values in brackets represent stack pointer register and the value at that location before each instruction is executed:
call redirect
(FFF4-04E6) push bp
(FFF2-FFF6) mov bp, sp
(FFF2-FFF6) mov fAddress, offest f
(FFF2-FFF6) pop originalBP
(FFF4-04E6) pop originalRIP
(FFF6-0000) push xx (I've changed xx to 1187)
(FFF4-0755) push originalRIP
(FFF2-04E6) push fAddress
(FFF0-04AC) push originalBP
(FFEE-FFF6) pop bp
(FFF0-04AC) ret
(in f) (FFF2-04E6) push bp
(FFF0-FFF6) mov bp,sp
printf executes
(FFF0-FFF6) pop bp
(FFF2-04E6) ret
Next statements seems to be return 0; which is the end of main.
Execution continues trough bunch of lines, and somehow comes back to the line calling redirect.
For you second snippet, the one without arguments, the stack states are as follow:
Where | Stack (growing on the left)
----------------------+----------------------------
after redirect prolog redirect rip, redirect bp
pop originalBP redirect rip
push fAddress redirect rip, fAddress
push originalBP redirect rip, fAddress, redirect bp
after redirect epilog redirect rip, fAddress
after redirect return redirect rip (control moved to f)
after f prolog redirect rip, f bp
after f epilog redirect rip
after f return (control moved to redirect caller)
Where redirect rip means the return address (return IP) of the function redirect.
As you can see, upon entering of f the stack correctly points to redirect rip, the return address of redirect.
Upon exit, the control flows back to redirect caller.
For your first snippet, the stack goes as follow:
Where | Stack (growing on the left)
----------------------+----------------------------
after redirect prolog redirect rip, redirect bp
pop originalBP redirect rip
push word ptr xx redirect rip, xx
push fAddress redirect rip, xx, fAddress
push originalBP redirect rip, xx, fAddress, redirect bp
after redirect epilog redirect rip, xx, fAddress
after redirect return redirect rip, xx (control moved to f)
after f prolog redirect rip, xx, f bp
after f epilog redirect rip, xx
after f return (control moved to xx)
Upon entering of f we have redirect rip, xx on the stack when we should really have xx, redirect rip.
with the former configuration the parameter aa contains the return address of redirect and the return address of f is the value of xx.
Based on your answer to my comment the code looped by accident.
If you want to call f with arguments, be sure to push them before the return address:
pop originalBP
pop originalRIP
;Arguments go here
push xx
push originalRIP
push fAddress
push originalBP
You didn't post what compiler and compiling options you use to code that redirect.
With optimizations ON, you can't assume the full C function prologue/epilogue will be used, so you are operating with stack without any idea of it's layout (if there would be zero prologue/epilogue, then you did inject 2 values ahead of return address to caller, so redirect would simply return to caller (main?) which may essentially just exit -> no call to f = not your case).
As inside the asm block you already have the fn address, why don't you simply call it? The stack would be like: somebody calls redirect -> redirect calls some address -> address fn() -> returns to redirect -> returns to caller.
It looks to me like you are trying to modify it to: somebody calls redirect -> redirect calls some address -> address fn() -> returns to caller (skipping return to redirect). As the redirect epilogue is tiny bit of code, I don't see much benefit of that modification (also I don't see how it is "context switch" related).
Anyway, check your compiler options how to produce the assembly listing of final code to see how it does really compile, or even better, check it with debugger (step per instruction on assembly level).
EDIT (after providing the debug info):
when you get to return 0, there's additional alien xx injected in stack (sp being 0xFFF4) instead of sp being original FFF6 pointing to the 0.
The end of main probably does not handle this correctly (doing pop bp ret I guess), assuming the sp is correct upon return. (would it do the other C epilogue including mov sp,bp, it would probably survive your stack tampering).
Then again, if it would do other epilogue in all functions, it would do it in redirect() too, so you would have to modify bp as well to make the end of redirect() do ret into fAddress. Like dec bp, dec bp would probably suffice, as you have grown the stack by injecting 2B into params space.
Check the debug one more time when return 0 in main is hit, how it is implemented, if it can cope with modified sp or not (well, obviously it can't, as it loops by accident into redirect).
If that's the case, you should probably patch the main to restore sp before return 0;. I wonder whether simple mov sp,bp would do (bp should be FFF6 ahead of that).
Conclusion: tampering with stack frames across several calls is always tricky business. ;)
So, are you heading toward something like this? (because I sort of can't exactly put my finger on where your code from question will be used then, seems like basic stack exercise to give you idea how code execution can be affected, which will later evolve probably into something like this... maybe... and maybe not).
Fake context switch in 16b in some C-like pseudo code (ok, more like comments only :) ), has to be installed as some timed interrupt:
// should be some "far" type function to preserve "cs" as well
far void fakeThreadSwitch() {
asm {
cli ; or other means to disable thread switch (re-entry)
; store the current values of all registers
pusha
pushf
push ds
push es
; set `ds` to thread contexts data section
; figure out, which thread is currently running
; (have some "size_t currently_running = index;" in context section)
; if none, then pick some SLEEPING
; but have some [root_context] updated (.stack), so you can
; do final switch to it upon terminating the OS.
; verify the ss points to that thread stack ->
; if you by accident did interrupt OS kernel,
; then just return without touching anything (jump to "pop es")
; store ss:sp to [current_thread_context.stack]
; decide if you want to switch to some other context
; (or kill current) simulating "preemptive multitasking"
; if switch, set up all flags correctly (RUNNING/SLEEPING/index)
; load ss:sp from [next_thread_context.stack]
pop es
pop ds
popf
popa
sti ; or enable thread switch interrupt by other means
}
}
Then to start some new thread executing code at fAddress:
void startNewThread(void far *fAddress) {
// allocate some new context for the new thread
// (probably fixed array for max threads, searching for "FREE" one)
// ... (inits fields in some struct [new_thread_context])
// allocate some new stack memory for the new thread
// ... (sets [new_thread_context.stack_allocated])
// set up the stack for initial threadSwitch
uint16_t far * stackEnd = [new_thread_context.stack]
// reserve: es,ds + flags + all + cs:ip (to be executed) + OS exit trap (3x)
stackEnd -= (2 + 1 + 8 + 2 + 3);
// init the values in "stack"
stackEnd[0] = stackEnd[1] = [new_thread_context.ds]; // es, ds
stackEnd[2] = 0; // flags
stackEnd[3] = stackEnd[4] = stackEnd[5] = 0; // di, si, bp
stackEnd[6] = offset(stackEnd+11); // sp ahead of "pusha"
stackEnd[7] = stackEnd[8] = 0; // bx, dx
stackEnd[9] = stackEnd[10] = 0; // cx, ax
stackEnd[11] = segment(fAddress); // "return" to fAddress
stackEnd[12] = offset(fAddress);
// thread_exit_return is some trap function to handle
// far return inside fAddress code, which would probably require
// different design to make this truly usable (to fit C epilogue of f())
stackEnd[13] = segment(&thread_exit_return);
stackEnd[14] = offset(&thread_exit_return);
stackEnd[15] = thread_id;
[new_thread_context.stack] = stackEnd;
// all context data are ready for context switch, mark this thread "ready"
[new_thread_context.running] = SLEEPING;
// now in some future the context-switch may pick this thread from
// pool of sleeping threads, and will switch execution to it
// (through this artificially prepared stack image)
}
One of kernel handlers, this one designed as "landing" point for any f() finishing normally, which would just return (or calling this explicitly).
void thread_exit_return() {
// get the exited thread_id somehow
[thread_context.running] = FINISHED;
// deallocate [thread_context.stack_allocated]
// deallocate thread context (marking it as "FREE"?)
}
Would require some more thought and design how to run kernel itself (whether in just another thread, or in the original app context), and how to give it running time. And how to control kernel to execute new threads, or kill/exit old ones.
Anyway, the important part of this exercise is that push-all-in-thread-stack / pop-all-from-other-stack, to give you rough idea how preemptive multitasking works (although in 32b protected OS this involves much more trickery with CPU switching to protected layer (and back to user land) and using different stack for kernel, etc.. so only the principle is same).
Of course in 16b unprotected this is quite fragile construction, which can be damaged across different threads easily (and I very likely did oversight something important, so it would require very likely some heavy bug fixing to make it work).

Calculating offset for hotpatching/inline function hooking

From http://lastfrag.com/hotpatching-and-inline-hooking-explained/,
Q1) Does code proceed from high memory to low memory or vice versa?
Q2) More importantly, during the calculation of the replacement offset, why is it that you have to minus the function preamble? Is it because the offset starts from the end of the instruction and not the beginning?
DWORD ReplacementAddressOffset = ReplacementAddress - OriginalAddress - 5;
Full Code:
void HookAPI(wchar_t *Module, char *API, DWORD Function)
{
HMODULE hModule = LoadLibrary(Module);
DWORD OriginalAddress = (DWORD)GetProcAddress(hModule, API);
DWORD ReplacementAddress = (DWORD)Function;
DWORD ReplacementAddressOffset = ReplacementAddress - OriginalAddress - 5;
LPBYTE pOriginalAddress = (LPBYTE)OriginalAddress;
LPBYTE pReplacementAddressOffset = (LPBYTE)(&ReplacementAddressOffset);
DWORD OldProtect = 0;
DWORD NewProtect = PAGE_EXECUTE_READWRITE;
VirtualProtect((PVOID)OriginalAddress, 5, NewProtect, &OldProtect);
for (int i = 0; i < 5; i++)
Store[i] = pOriginalAddress[i];
pOriginalAddress[0] = (BYTE)0xE9;
for (int i = 0; i < 4; i++)
pOriginalAddress[i + 1] = pReplacementAddressOffset[i];
VirtualProtect((PVOID)OriginalAddress, 5, OldProtect, &NewProtect);
FlushInstructionCache(GetCurrentProcess(), NULL, NULL);
FreeLibrary(hModule);
}
Q3) In this code, the relative address of a jmp instruction is being replaced; relAddrSet is a pointer to the original destination; to is a pointer to the new destination. I don't understand the calculation of the to address, why is it that you have to add the original destination to the functionForHook + opcodeOffset?
DWORD *relAddrSet = (DWORD *)(currentOpcode + 1);
DWORD_PTR to = (*relAddrSet) + ((DWORD_PTR)functionForHook + opcodeOffset);
*relAddrSet = (DWORD)(to - ((DWORD_PTR)originalFunction + opcodeOffset));
Yes the relative address is the the offset after the instructions, that's why you have to substract 5.
But, in my opinion, you should just forget the idea of the relative jump and try absolute jump.
Why ? Because it is a lot easier and x86-64 compatible (relative jumps are limited to +/-2GB).
The absolute jump is (x64) :
48 b8 ef cd ab 89 67 45 23 01 mov rax, 0x0123456789abcdef
ff e0 jmp rax
And for x86 :
b8 67 45 23 01 mov eax, 0x01234567
ff e0 jmp eax
Here is the modified code (the loader is now 7 bytes instead of 5):
void HookAPI(wchar_t *Module, char *API, DWORD Function)
{
HMODULE hModule = LoadLibrary(Module);
DWORD OriginalAddress = (DWORD)GetProcAddress(hModule, API);
DWORD OldProtect = 0;
DWORD NewProtect = PAGE_EXECUTE_READWRITE;
VirtualProtect((PVOID)OriginalAddress, 7, NewProtect, &OldProtect);
memcpy(Store, OriginalAddress, 7);
memcpy(OriginalAddress, "\xb8\x00\x00\x00\x00\xff\xe0", 7);
memcpy(OriginalAddress+1, &ReplacementAddress, sizeof(void*));
VirtualProtect((PVOID)OriginalAddress, 7, OldProtect, &NewProtect);
FlushInstructionCache(GetCurrentProcess(), NULL, NULL);
FreeLibrary(hModule);
}
The code is the same for x64 but you have to add 2 nops (90) at the beginning or the end in order match the size of the following instructions, so the loader is "\x48\xb8<8-bytes addr>\xff\xe0\x90\x90" (14 bytes)
Q1) The program runs from lower to highest addresses (i.e. the program counter gets increased by the size of each instruction, unless in case of jumps, calls or ret). But I am probably missing the point of the question.
Q2) Yes, on x86 the jumps are executed after the program counter has been increased by the size of the jump instruction (5 bytes); when the CPU adds the jump offset to the program counter to calculate the target address, the program counter has already been increased of 5.
Q3) This code is quite weird, but it may work. I suppose that *relAddrset initially contains a jump offset to originalFunction (i.e. *relAddSet==originalFunction-relativeOffset). If this is true, the final result is that *reladdrSet contains a jump offset to functionFoHook. Indeed the last instruction becomes:
*relAddrSet=(originalFunction-relativeOffset)+functionForHook-originalFunction
== functionForHook-relativeOffset
Yes, code runs "forward" if I understand this question correctly. One instruction is executed after another if it is not branching.
An instruction that does a relative jump (JMP, CALL) does the jump relative to the start of the next instruction. That's why you have to subtract the length of the instruction (here: 5) from the difference.
I can't answer your third question. Please give some context and what the code is supposed to do.

memcpy() crashes randomly

I am using memcpy in my application. memcpy crashes randomely and below is the logs i got in Dr.Watson files.
100181b5 8bd1 mov edx,ecx
100181b7 c1e902 shr ecx,0x2
100181ba 8d7c030c lea edi,[ebx+eax+0xc]
100181be f3a5 rep movsd
100181c0 8bca mov ecx,edx
100181c2 83e103 and ecx,0x3
FAULT ->100181c5 f3a4 rep movsb ds:02a3b000=?? es:01b14e64=00
100181c7 ff1508450210 call dword ptr [Debug (10024508)]
100181cd 83c424 add esp,0x24
100181d0 6854580210 push 0x10025854
100181d5 ff1508450210 call dword ptr [Debug (10024508)]
100181db 83c404 add esp,0x4
Below is the code
memcpy((char *)dep + (int)sizeof(EntryRec) + (int)adp->fileHdr.keySize, data, dataSize );
Where:
dep is a structure
EntryRec is a charecter pointer
adp is a structure
data is not NULL in this case
Has anyone faced this issue and can help me?
I have tried to debug the prog,
then i got the following error
Unhandled exception in Prog.exe(MSVCRTD.DLL):0xC0000005: Access voilation
Data is passed argument for this program and this is void*
Further Info:
I have tried to Debug the code adapter is crashing in the following area this function is present in OUTPUT.c (I think this is a library function)
#else /* _UNICODE */
if (flags & (FL_LONG|FL_WIDECHAR)) {
if (text.wz == NULL) /* NULL passed, use special string */
text.wz = __wnullstring;
bufferiswide = 1;
pwch = text.wz;
while ( i-- && *pwch )
++pwch;
textlen = pwch - text.wz;
/* textlen now contains length in wide chars */
} else {
if (text.sz == NULL) /* NULL passed, use special string */
text.sz = __nullstring;
p = text.sz;
while (i-- && *p) //Crash points here
++p;
textlen = p - text.sz; /* length of the string */
}
Value for variables:
p= ""(not initialised)
i= 2147483598
There are two very likely explanations:
You are using memcpy across overlapping addresses -- the behavior of this situation is undefined. If you require the ability to handle overlapping addresses, std::memmove is the "equivalent" tool.
You are using memcpy to copy to/from memory that is inaccessible to your program.
From the code you've shown, it looks like (2) is the more likely scenario. Since you are able to debug the source, try setting a breakpoint before the memcpy occurs, and verify that the arguments to memcpy all match up (i.e. source + num < dest or source > dest + num).
From the disassembled code it appears that the source pointer is not in your address space.
rep movsb copies from ds:si to es:di. The ?? indicates that the memory at ds:si could not be read.
Is the data pointed to by (char *)dep + (int)sizeof(EntryRec) + (int)adp->fileHdr.keySize always at least dataSize long?
I have come across similar crashes where variable length strings are later treated like fixed with strings.
eg
char * ptr = strdup("some string");
// ...
memcpy(ptr, dest, fixedLength);
Where fixedLength is greater than 10. Obviously these were in different functions so the length issue was not noticed. Most of the time this will work, dest will contain "some string" and after the null will be random garbage. In this case if you treat dest as a null terminated string you will never notice, as you don't see the garbage after the null.
However if ptr is allocated at the end of a page of memory, you can only read to the end of the allocated memory and no further. As soon as you read past the end of the page the operating system will rightly crash your program.
It looks like you've run over the end of a buffer and generated an access violation.
Edit: There still is not enough information. We cannot spot a bug without knowing much more about how the buffer you are trying to copy to is allocated whether it has enough space (I suspect it does not) and whether dataSize is valid.
If memcpy crashes the usual reason is, that you passed illegal arguments.
Note that with memcpy source and destination may not overlap.
In such a case use memmove.
from your code "memcpy((char *)dep + (int)sizeof(EntryRec) + (int)adp->fileHdr.keySize, data, dataSize)" and the debug infomation, the "data" looks like a local variable (on-stack variable), you'd do "data = malloc(DATA_SIZE)" instead of "char data[DATA_SIZE]" etc; otherwise, at your current code line, the "data" was popped already, so may cause memory accessing fault randomly.
I'd suggest using memmove as this handles overlapping strings, when using memcpy in this situation the result is unpredictable.