push eax
push str_checkSell
call CELUA_ExecuteFunction //we assume this returns 1
test eax, eax
jz AutoMarketInc // This doesnt effect the programm cause eax = 1
push eax // Why do we push eax again?
push str_getSellQuantity
call CELUA_ExecuteFunction // we assume this returns 1
push eax // why to we push eax two times?
push eax //
push str_getGood
call CELUA_ExecuteFunction // This returns 2
push eax //this eax now 2?
push 1 //just a one on the stack I assume?
call 004CBFA0 // Function call with arguments? (Func takes 3 arguments)
So far so good, now I want to replace the Lua-Functions with static values
push eax
mov eax,1
test eax, eax
jz AutoMarketInc // This doesnt effect the programm cause eax = 1
push eax // Why do we push eax again?
mov eax,1
push eax // why to we push eax two times?
push eax //
mov eax,2
push eax //this eax now 2?
push 1 //just a one on the stack I assume?
call 004CBFA0 // Function call with arguments? (Func takes 3 arguments)
Am I understand this whole thing correctly? Are my comments correct?
When I repalce the first code with the second one my target process crashes which I try to manipulate.
In case you need further informations:
Its about a game where you can micro manage goods, the function call 004CBFA0 sells items
The code is not mine its an Script which handles the auto sell and works well. But I just replaced the lines as you can see above and its not working anymore? Shouldnt it work cause I just use static values instead of dynamic ones?
LUA Script:
----------------
-- Goods List --
----------------
GOODS_ID = {}
GOODS_ID.wood = 2
GOODS_ID.hop = 3
GOODS_ID.stone = 4
GOODS_ID.iron = 6
GOODS_ID.pitch = 7
GOODS_ID.wheat = 9
GOODS_ID.bread = 10
GOODS_ID.cheese = 11
GOODS_ID.meat = 12
GOODS_ID.fruit = 13
GOODS_ID.beer = 14
GOODS_ID.flour = 16
GOODS_ID.bow = 17
GOODS_ID.xbow = 18
GOODS_ID.spear = 19
GOODS_ID.pike = 20
GOODS_ID.mace = 21
GOODS_ID.sword = 22
GOODS_ID.leather = 23
GOODS_ID.armor = 24
-----------------
-- Lua Scripts --
-----------------
good_id = 1
-- current good, or more precise, index of MARKET_LIST
function getGood()
-- returns current good id
return GOODS_ID[MARKET_LIST[good_id][1]]
end
function getGoodCount(good)
-- returns current number of good in stockple/granary/armory
local GOODS_BASE = 0x0115FCBC -- 1.4.1
return readInteger(GOODS_BASE + 4 * GOODS_ID[good])
end
function checkBuy()
-- returns 1 if current something of the current good should be bought, else 0
local good_arr = MARKET_LIST[good_id]
if getGoodCount(good_arr[1]) < good_arr[2] - good_arr[4] then
return 1
end
return 0
end
function getBuyQuantity()
-- returns how much of the current good should be bought
local good_arr = MARKET_LIST[good_id]
local count = getGoodCount(good_arr[1])
return good_arr[2] - count
end
function checkSell()
-- returns 1 if current something of the current good should be sold, else 0
local good_arr = MARKET_LIST[good_id]
if getGoodCount(good_arr[1]) > good_arr[3] + good_arr[5] then
return 1
end
return 0
end
function getSellQuantity()
-- returns how much of the current good should be sold
local good_arr = MARKET_LIST[good_id]
local count = getGoodCount(good_arr[1])
return count - good_arr[3]
end
function nextGood()
-- increments good_id for next iteration
if good_id < #MARKET_LIST then
good_id = good_id + 1
else
good_id = 1
end
end
{$lua}
------------------
-- Market Setup --
------------------
--[[
You can add any good you want to trade to the automatic market by adding
{"good", min, max, min_variance, max_variance}
to the MARKET_LIST. All goods below the MARKET_LIST.
Check, that min-min_variance > 0.
The market only buys or sells one good per gametick!
--]]
MARKET_LIST = {
{"wood", 10, 25, 5, 10},
{"bread", 15, 50, 5, 20},
{"cheese", 15, 50, 5, 20},
{"meat", 15, 50, 5, 20},
{"fruit", 15, 50, 5, 20}}
--[[
wood
hop
stone
iron
pitch
wheat
bread
cheese
meat
fruit
beer
flour
bow
xbow
spear
pike
mace
sword
leather
armor
--]]
---------------------
-- Assembly Script --
--- Don't touch ! ---
---------------------
{$asm}
loadlibrary(luaclient-i386.dll)
luacall(openLuaServer('CELUASERVER'))
CELUA_ServerName:
db 'CELUASERVER',0
alloc(functionid,32)
alloc(str_getGood,64)
alloc(str_checkBuy,64)
alloc(str_getBuyQuantity,64)
alloc(str_checkSell,64)
alloc(str_getSellQuantity,64)
alloc(str_nextGood,64)
str_getGood:
db 'return getGood(parameter)',0
str_checkBuy:
db 'return checkBuy(parameter)',0
str_getBuyQuantity:
db 'return getBuyQuantity(parameter)',0
str_checkSell:
db 'return checkSell(parameter)',0
str_getSellQuantity:
db 'return getSellQuantity(parameter)',0
str_nextGood:
db 'return nextGood(parameter)',0
[ENABLE]
aobscanmodule(AutoMarketInject,Stronghold Crusader.exe,E9 9F E7 FF FF)
alloc(AutoMarketMem,$1000)
label(AutoMarketInit)
label(AutoMarketBuy)
label(AutoMarketSell)
label(AutoMarketInc)
label(AutoMarketReturn)
registersymbol(AutoMarketInject)
registersymbol(AutoMarketMem)
registersymbol(AutoMarketInit)
registersymbol(AutoMarketBuy)
registersymbol(AutoMarketSell)
registersymbol(AutoMarketInc)
registersymbol(AutoMarketReturn)
AutoMarketInject:
jmp AutoMarketMem
AutoMarketMem:
AutoMarketInit:
push ecx
// checks if appropriate gametick
cmp dword ptr [117CACC],00
jz AutoMarketReturn
AutoMarketBuy:
// checks and might buy
push eax
push str_checkBuy
call CELUA_ExecuteFunction
test eax,eax
jz AutoMarketSell
push eax
push str_getBuyQuantity
call CELUA_ExecuteFunction
push eax
push eax
push str_getGood
call CELUA_ExecuteFunction
push eax
push 1
call 004CC000
jmp AutoMarketInc
AutoMarketSell:
// checks and might sell
push eax
push str_checkSell
call CELUA_ExecuteFunction
test eax, eax
jz AutoMarketInc
push eax
push str_getSellQuantity
call CELUA_ExecuteFunction
push eax
push eax
push str_getGood
call CELUA_ExecuteFunction
push eax
push 1
call 004CBFA0
AutoMarketInc:
// increments current good
push eax
push str_nextGood
call CELUA_ExecuteFunction
AutoMarketReturn:
// return
pop ecx
jmp 0045B4A0
[DISABLE]
AutoMarketInject:
db E9 9F E7 FF FF
dealloc(AutoMarketMem)
dealloc(str_getGood,64)
dealloc(str_checkBuy,64)
dealloc(str_getBuyQuantity,64)
dealloc(str_checkSell,64)
dealloc(str_getSellQuantity,64)
dealloc(str_nextGood,64)
unregistersymbol(AutoMarketInject)
unregistersymbol(AutoMarketMem)
unregistersymbol(AutoMarketInit)
unregistersymbol(AutoMarketBuy)
unregistersymbol(AutoMarketSell)
unregistersymbol(AutoMarketInc)
unregistersymbol(AutoMarketReturn)
Source: https://github.com/UnofficialCrusaderPatch/UnofficialCrusaderPatch/issues/512
I'm making the assumption that the calling convention for the function CELUA_ExecuteFunction is that the called function removes its parameters from the stack when it returns. I'm pretty sure that is correct, because the code doesn't make sense otherwise.
All of the pushes in this code are placing parameters on the stack in preparation for a function call. For each function call you remove, you must also remove the code that pushes its parameters, so that the stack remains balanced.
The first two pushes are parameters to the first function call, which you removed, so you should also remove both of the pushes, not just the second one.
The next two pushes are parameters to the second function call. Again, you need to remove both.
The next push is the third parameter to the function 004CBFA. You need to keep this one. (The value is the return value of getSellQuantity.)
The next two pushes are parameters to the third function call. Again, you need to remove both. Note that the second parameter to getGood is the same as the third parameter to 004CBFA. That's why eax is pushed twice.
After removing the parameters to the function calls that you removed, you are left with only 3 pushes: push 1, push 2, and push 1.