Spawning items in DayZ/Arma2OA

This is a copy of the article I wrote on UnknownCheats regarding manually spawning items and weapons through memory manipulation in Arma2OA.  I would add that Arma uses its own memory manager, tbb4malloc_bi.dll by default.  Arma also has a garbage collection system, so when an item’s references reaches 0 OR the game loads a new mission, the garbage collector frees the item.  If you use regular malloc to allocate the memory you use to spawn an item, you will crash when Arma tries to garbage collect that item, because the Arma memory manager is trying to free something it didn’t allocate.  To get around this, you can just  call Arma’s memory manager’s Alloc function that way it can free the alloc’d item.  I popped open tbb4malloc_bi.dll and found the address of the function (it’s in the export table) and made a function pointer to it in my version:

_MemAlloc = 0;
HMODULE hMalloc =  GetModuleHandle(“tbb4malloc_bi.dll”);
if(hMalloc)
{
_MemAlloc = (MemAlloc)((char *)hMalloc + 0x7A90);
if(*(DWORD *)_MemAlloc != 0x56ec8b55)
_MemAlloc = 0;
}

I then made a memory allocation function that calls the right version (_MemAlloc or malloc) depending on what’s available

void *allocateMem(SIZE_T size)
{
if(_MemAlloc)
return _MemAlloc(size);
else
return malloc(size);
}

You can’t use a single pointer and set it to either _MemAlloc or malloc because they have different calling conventions, so this was my solution.  Maybe not especially elegant, but it works, and my users that use different memory managers can still use the hack.  I could find all the allocation functions for each possible memory manager (Arma offers quite a few) but…it’s not that big a priorty really.

Anyway, here is the original article:

 

I know this is old hat to most of you, but a lot of people (like me) are just now figuring this stuff out, so bear with me. And I am not working from an external program so I’m not actually working with WriteProcessMemory so sorry for the misleading thread title.

Most people have figured out how to copy weapons and consumables from tents, vehicles, and other players. But what about just spawning without having to search for it? Or what if you want an item that doesn’t exist currently on the map? Or what if you want a bunch of a single consumable that don’t share the same pointer (and thus affect each other when something is done to one)?

Theoretically, it must be possible, right? Surely there is a table of weapons somewhere, and likewise for consumables. If we track those down, we should be able to add anything we want to our inventory, right? Well, kind of.

How items are stored in memory in Arma 2OA

There exist three fun tables in your player class: your weapon/non-consumable table, your weapon data table, and your consumable table. The pointer to each table is followed by the current size and the max size allocated for that table.

The current size of each table indicates the number of items in it. If you have 6 items and you set it to 0, your in-game inventory will appear empty. The pointers to those items remain in the table, however, so if you set the size back to 6 your items will reappear.

Weapons

Weapons are easy. If you have copied them into your inventory by hand you have probably noticed that each instance of a given weapon shares the same pointer. Allow me to demonstrate:

This image has been resized. Click this bar to view the full image. The original image is sized 713×172.

That is a snapshot of my weapon table which I named itemTable. You can see it’s just a collection of pointers to weapons and non-consumables. Non-consumables include night vision goggles, maps, compasses, etc. Highlighted is the entry for my gun, an M16A4. You can see the pointer points to 0xC369A80.

So I dropped that gun on the ground and picked up a new M16A4 from this ammo box here.

This image has been resized. Click this bar to view the full image. The original image is sized 962×665.

And here is the new snapshot of my non-consumable table:

This image has been resized. Click this bar to view the full image. The original image is sized 702×169.

Check out that last entry: 0xC369A80! The exact same address as the other weapon. Any M16A4 on any entity in that mission would have had an address of 0xC369A80, meaning we could copy that address into our table all day long and get fresh new M16A4’s! You could drop them, give them to other people, stuff helicopters full of them, whatever you want to do.

Copying weapons from other players
But how do we get that pointer to copy? If we already had the gun we probably wouldn’t need to copy it that bad. Well, I already mentioned copying from other players’ inventories, and it turns out it’s super simple. It turns out that +0x8 in each weaponvaluetable entry, often called the weaponArray, is the same pointer that is in the non-consumable table. So to steal a weapon from someone, you would do something like:

Code:
localPlayer->nonConsumableTable[localPlayer->nonConsumableSize].item = target->weaponArray[target->weaponID].weapon;
localPlayer->nonConsumableSize++;

That will copy whatever weapon they currently have out into your inventory. You will have to drop it and pick it back up to use it because copying it into inventory does not populate the weaponarray entries. Or I suppose you could build the weaponarray entry yourself…

Creating weapons from the weapons table

Remember me theorizing that there was probably a table that had all the weapons in one place? Turns out it’s at 0xDFCD00] + 0], with the size of the table at 0xDFCD00] + 0x4. It’s just a table of pointers to weapon classes, so each entry is 0x4 bytes long. ALL you have to do to spawn a weapon into your inventory is copy one of those pointers into your non-consumables table. You can work your way to a string with the name of the weapon through the weapon struct so either search for a specific weapon or iterate through the table until you find what you want. 2EZ.

Consumables

Consumables are a different story. Here’s why. This is a picture of my inventory table which has nothing but M16 mags in it:

This image has been resized. Click this bar to view the full image. The original image is sized 706×175.

Notice that each entry is a different pointer, despite each item being the same exact item. Why? Well think about it, if they all pointed to the same struct, any change to one (like changing the ammo value) would change all the others. This makes creating consumables out of thin air problematic. There is no table of constructed consumable templates (trust me, I’ve looked). We can still copy them, however.

Copying consumables from other players

When I copied weapons from players, I would copy a single magazine from them as well. The pointer at 0x4 in the weaponArray is a pointer to the magazine currently loaded in the weapon – I would just copy that into my own inventory so I would be sure to have a magazine with my copied weapon! I think this was a cause of a lot of my crashes because of Arma’s garbage collection system, but more on that later.

It’s done the exact same way as weapons. Find the consumable you want to copy, and write its pointer into your consumable array. Then, increment the consumable table size, taking care not to go over the max. In DayZ I think it starts at like 32 so you should be good.

Spawning consumables from scratch

Whoa wait a minute, I thought there didn’t exist a table of pre-built consumable data structures that we could copy out of? Well, there doesn’t! But there does exist a table of what I call “Magazine types”, or the pointer that is 0x8 in the magazine/consumable class. You know, where you read your maxCapacity from? That struct. That table is at 0xDFCDC0] with the size of the table at 0xDFCDC4. But how does that help us?

Let’s take a look at the consumable data structure.

This image has been resized. Click this bar to view the full image. The original image is sized 822×380.

Those are two M16 magazines expanded so you can see what’s in the structure. Highlighted is the pointer to the “magazine type” structure, where maxcapacity is. Notice that the two magazines, both in separate places in memory, have an identical magazine type pointer. Any of the same type of consumable will share that pointer! So we know if we want to make an M16 magazine, we need to search for the Stanag mag type in the mag type table and use the pointer to that in our new magazine structure.

But what about the rest? Here’s my breakdown of the consumable structure:

Code:
	void* methods; //0x0000,
	__int32 references; //0x0004 
	magazineInfo* magInfo; //0x0008 
	__int32 ammo1; //0x000C 
char _0x0010[4];
	float fireTimer; //0x0014 
	float fireTimerCoefficient; //0x0018 
char _0x001C[8];
	__int32 ammo2; //0x0024 
	__int32 Type; //0x0028 
	__int32 itemID; //0x002C

methods – a pointer to the VMT of the magazine class. All consumables have the same value here
references – Arma 2 has a garbage collection system. If the number of references to an item reaches 0, it is freed. This is problematic, if we copy an item and don’t set its reference count correctly, it could get freed and cause a crash.
magInfo – pointer to the magazine type structure we talked about earlier.
ammo1/ammo2 – the ammo values. See my thread on setting that here Infinite Ammo via WPM
char buffer – both of these can be safely set to 0
Type – I don’t know what this is, but all consumables share the same value.
itemID – self explanatory, items are numbered upon creation.

Do you see where this is going? By looking at one other consumable we can get valid values for each of these pieces of data in the magazine struct. And if we can get valid values for each of them, what can we do? Why, malloc some memory and create our own item instance!

Code:
    cMagazine *newItem = (cMagazine *)malloc(sizeof(cMagazine));
memset(newItem, 0, sizeof(cMagazine));
newItem->Type = LocalPlayer->inventoryTable[0].item->Type;
...
...

LocalPlayer->inventoryTable[LocalPlayer->inventoryTableSize].item = newItem;
LocalPlayer->inventoryTableSize++;

That’s all you gotta do, malloc yourself 0x2C bytes of space and write the appropriate values. Then write a pointer to that in your table and you’re done. You might even write into weapon holders instead so it looks less suspicious in the logs.What I do is:

Malloc and zero out the memory

Copy the VMT pointer, type, and reference count from an existing item. The reference count varies depending on if your inventory is open, the item is loaded in a gun, etc. so I find this the safest route. You may end up never freeing those items but that’s a pretty small memory leak, I wouldn’t worry about it.

Get the itemID of an existing item in my inventory and save that. Every time I spawn an item, I increment it and use that value as the itemID of the spawned item. Setting multiple items to the same itemID seems to have no affect on gameplay, but may show up in the logs.

Set the magType pointer to whatever item it is I want to spawn

Set ammo1 and ammo2 based on maxCapacity from the magType struct

Don’t worry about the buffers or the fire timer data, that can all safely be 0.

The item is now created, I add it straight to my inventory but if I was worried about getting caught I might write it on an existing weapon pile and loot it from that.

It’s 2EZ, and super fun to spam Cherno with bear traps and sandbag barriers. And if you’re bored of just blasting everyone all the time, like I am, you can leave all kinds of high end weapons and gear in Elektro or Cherno and watch fresh spawns kill each other and blow everything up, it’s a lot of fun!

2 thoughts on “Spawning items in DayZ/Arma2OA

  1. wow, very well explained and pretty clever. managed to spawn consumables and weapos from scratch – from “external” (im a noob, new to programming and reverse engineering). everything is working, but experienced crashes because im using VirtualAllocEx to alloc mem. is there any way to use the arma memory manager /alloc function from external?

    • The only way I would know of is creating a thread in the Arma process that allocates the memory, and getting the information on where that allocated memory is in the external process (i.e. virtualallocex two pieces of memory, one will be a pointer pointer that will point to the allocated memory, one will be bytecode which will call the arma alloc and write the pointer to the allocated memory in the first piece of memory you allocated, then your external can use that piece of memory). I may try this out and write something on it.

Leave a comment