Pre-class remove
parent
e887c60e93
commit
f1d4eac700
Binary file not shown.
@ -0,0 +1,111 @@
|
|||||||
|
local _ENV = mkmodule('plugins.dfusion.friendship')
|
||||||
|
local dfu=require("plugins.dfusion")
|
||||||
|
local ms=require("memscan")
|
||||||
|
|
||||||
|
local MAX_RACES=100
|
||||||
|
local MAX_CODE_DIST=250
|
||||||
|
FriendshipRainbow=defclass(FriendshipRainbow,dfu.BinaryPlugin)
|
||||||
|
FriendshipRainbow.name="FriendshipRainbow"
|
||||||
|
-- os independant... I think...
|
||||||
|
FriendshipRainbow.ATTRS{filename="hack/lua/plugins/dfusion/friendship.o",name="FriendshipRainbow",race_data=DEFAULT_NIL}
|
||||||
|
FriendshipRainbow.class_status="valid, not installed"
|
||||||
|
function FriendshipRainbow:find_one(codesg,needle,crace)
|
||||||
|
dfu.concatTables(needle,dfu.dwordToTable(crace))
|
||||||
|
return codesg.uint8_t:findall(needle)
|
||||||
|
end
|
||||||
|
function FriendshipRainbow:find_all()
|
||||||
|
local code=ms.get_code_segment()
|
||||||
|
local locations={}
|
||||||
|
local _,crace=df.sizeof(df.global.ui:_field("race_id"))
|
||||||
|
|
||||||
|
dfu.concatTables(locations,self:find_one(code,{0x66,0xa1},crace)) --mov ax,[ptr]
|
||||||
|
dfu.concatTables(locations,self:find_one(code,{0xa1},crace)) --mov ax,[ptr]
|
||||||
|
local registers=
|
||||||
|
{0x05, -- (e)ax
|
||||||
|
0x1d, --ebx
|
||||||
|
0x0d, --ecx
|
||||||
|
0x15, --edx
|
||||||
|
0x35, --esi
|
||||||
|
0x3d, --edi
|
||||||
|
--0x25, --esp not used?
|
||||||
|
--0x2d, --ebp not used?
|
||||||
|
}
|
||||||
|
for k,reg in ipairs(registers) do
|
||||||
|
|
||||||
|
dfu.concatTables(locations,self:find_one(code,{0x0f,0xbf,reg},crace)) --movsx reg,[ptr]
|
||||||
|
dfu.concatTables(locations,self:find_one(code,{0x66,0x8b,reg},crace)) --mov reg,[ptr]
|
||||||
|
end
|
||||||
|
printall(locations)
|
||||||
|
return self:filter_locations(code,locations)
|
||||||
|
end
|
||||||
|
function FriendshipRainbow:filter_locations(codesg,locations)
|
||||||
|
local ret={}
|
||||||
|
local registers={0x80,0x83,0x81,0x82,0x86,0x87,
|
||||||
|
0x98,0x9b,0x99,0x9a,0x9e,0x9f,
|
||||||
|
0x88,0x8b,0x89,0x8a,0x8e,0x8f,
|
||||||
|
0x90,0x93,0x91,0x92,0x96,0x97,
|
||||||
|
0xb0,0xb3,0xb1,0xb2,0xb6,0xb7,
|
||||||
|
0xb8,0xbb,0xb9,0xba,0xbe,0xbf}
|
||||||
|
for _,entry in ipairs(locations) do
|
||||||
|
for _,r in ipairs(registers) do
|
||||||
|
|
||||||
|
local idx,addr=codesg.uint8_t:find({0x39,r,0x8c,0x00,0x00,0x00},
|
||||||
|
codesg.uint8_t:addr2idx(entry[2]),codesg.uint8_t:addr2idx(entry[2])+MAX_CODE_DIST)
|
||||||
|
if addr then
|
||||||
|
table.insert(ret,{addr,r})
|
||||||
|
break
|
||||||
|
end
|
||||||
|
idx,addr=codesg.uint8_t:find({0x3b,r,0x8c,0x00,0x00,0x00},
|
||||||
|
codesg.uint8_t:addr2idx(entry[2]),codesg.uint8_t:addr2idx(entry[2])+MAX_CODE_DIST)
|
||||||
|
if addr then
|
||||||
|
table.insert(ret,{addr,r})
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
function FriendshipRainbow:patchCalls(target)
|
||||||
|
local addrs=self:find_all()
|
||||||
|
local swaps={}
|
||||||
|
for k,adr in ipairs(addrs) do
|
||||||
|
local newval=dfu.makeCall(adr[1],target)
|
||||||
|
table.insert(newval,adr[2])
|
||||||
|
for t,val in ipairs(newval) do
|
||||||
|
swaps[adr[1]+t-1]=val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
dfhack.internal.patchBytes(swaps)
|
||||||
|
end
|
||||||
|
function FriendshipRainbow:set_races(arr)
|
||||||
|
local n_to_id=require("plugins.dfusion.tools").build_race_names()
|
||||||
|
local ids={}
|
||||||
|
for k,v in ipairs(self.race_data) do -- to check if all races are valid.
|
||||||
|
ids[k]=n_to_id[v]
|
||||||
|
end
|
||||||
|
for k,v in ipairs(ids) do
|
||||||
|
arr[k-1]=ids[k]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function FriendshipRainbow:install(races)
|
||||||
|
self.race_data=races or self.race_data
|
||||||
|
if #self.race_data<1 then
|
||||||
|
error("race count must be bigger than 0")
|
||||||
|
end
|
||||||
|
if #self.race_data>MAX_RACES then
|
||||||
|
error("race count must be less then "..MAX_RACES)
|
||||||
|
end
|
||||||
|
local rarr=self:allocate("race_array",'uint16_t',MAX_RACES)
|
||||||
|
local _,rarr_offset=df.sizeof(rarr)
|
||||||
|
self:set_marker_dword("racepointer",rarr_offset)
|
||||||
|
self:set_races(rarr)
|
||||||
|
self:set_marker_dword("racecount",#self.race_data)
|
||||||
|
local safe_loc=self:allocate("safe_loc",'uint32_t',1)
|
||||||
|
local _1,safe_loc_offset=df.sizeof(safe_loc)
|
||||||
|
self:set_marker_dword("safeloc1",safe_loc_offset)
|
||||||
|
self:set_marker_dword("safeloc2",safe_loc_offset)
|
||||||
|
local addr=self:move_to_df()
|
||||||
|
self:patchCalls(addr)
|
||||||
|
self.installed=true
|
||||||
|
end
|
||||||
|
return _ENV
|
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
as -anl --32 -o friendship.o friendship.asm
|
@ -0,0 +1,7 @@
|
|||||||
|
.intel_syntax
|
||||||
|
mov eax , [esp+0x1C] # loop counter
|
||||||
|
mark_caste:
|
||||||
|
movsx ecx, word ptr[eax*2+0xdeadbeef]
|
||||||
|
mark_race:
|
||||||
|
movzx eax,word ptr [eax*2+0xDEADBEEF]
|
||||||
|
ret
|
@ -0,0 +1,106 @@
|
|||||||
|
.intel_syntax
|
||||||
|
push eax
|
||||||
|
mov eax,[esp+0x04]
|
||||||
|
push ebx
|
||||||
|
pushfd
|
||||||
|
mov eax,[eax] # get a byte after the call this procedure to analyze what register holds cr ptr
|
||||||
|
jmptbl:
|
||||||
|
cmp al,0x81
|
||||||
|
jz regC
|
||||||
|
cmp al,0x82
|
||||||
|
jz regD
|
||||||
|
cmp al,0x83
|
||||||
|
jz regB
|
||||||
|
cmp al,0x85
|
||||||
|
jz regBP
|
||||||
|
cmp al,0x86
|
||||||
|
jz regESI
|
||||||
|
cmp al,0x87
|
||||||
|
jz regEDI
|
||||||
|
cmp al,0x88
|
||||||
|
jz regA
|
||||||
|
cmp al,0x8A
|
||||||
|
jz regD
|
||||||
|
cmp al,0x8B
|
||||||
|
jz regB
|
||||||
|
cmp al,0x8D
|
||||||
|
jz regBP
|
||||||
|
cmp al,0x8E
|
||||||
|
jz regESI
|
||||||
|
cmp al,0x8F
|
||||||
|
jz regEDI
|
||||||
|
cmp al,0x90
|
||||||
|
jz regA
|
||||||
|
cmp al,0x91
|
||||||
|
jz regC
|
||||||
|
cmp al,0x93
|
||||||
|
jz regB
|
||||||
|
cmp al,0x95
|
||||||
|
jz regBP
|
||||||
|
cmp al,0x96
|
||||||
|
jz regESI
|
||||||
|
cmp al,0x97
|
||||||
|
jz regEDI
|
||||||
|
jmp fail
|
||||||
|
regA:
|
||||||
|
mov eax, [esp+0x8]
|
||||||
|
mov eax, [eax+0x8c]
|
||||||
|
jmp compare
|
||||||
|
regC:
|
||||||
|
mov eax, [ecx+0x8c]
|
||||||
|
jmp compare
|
||||||
|
regB:
|
||||||
|
mov eax, [ebx+0x8c]
|
||||||
|
jmp compare
|
||||||
|
regD:
|
||||||
|
mov eax, [edx+0x8c]
|
||||||
|
jmp compare
|
||||||
|
regBP:
|
||||||
|
mov eax, [ebp+0x8c]
|
||||||
|
jmp compare
|
||||||
|
regESI:
|
||||||
|
mov eax, [esi+0x8c]
|
||||||
|
jmp compare
|
||||||
|
regEDI:
|
||||||
|
mov eax, [edi+0x8c]
|
||||||
|
#jmp compare
|
||||||
|
compare:
|
||||||
|
push ecx
|
||||||
|
mark_racepointer:
|
||||||
|
mov ebx,0xDEADBEEF #write a pointer to the list of allowed races
|
||||||
|
mark_racecount:
|
||||||
|
mov ecx,0xDEADBEEF #write a number of allowed races
|
||||||
|
loop1:
|
||||||
|
cmp word[ebx+ecx*2],ax
|
||||||
|
jz endok
|
||||||
|
dec ecx
|
||||||
|
cmp ecx ,-1
|
||||||
|
jnz loop1
|
||||||
|
pop ecx
|
||||||
|
popfd
|
||||||
|
jmp fail
|
||||||
|
endok:
|
||||||
|
pop ecx
|
||||||
|
popfd
|
||||||
|
cmp eax,eax
|
||||||
|
jmp endfinal
|
||||||
|
fail:
|
||||||
|
|
||||||
|
xor ebx,ebx
|
||||||
|
xor eax,eax
|
||||||
|
inc eax
|
||||||
|
cmp eax,ebx
|
||||||
|
endfinal:
|
||||||
|
|
||||||
|
pop ebx
|
||||||
|
pop eax
|
||||||
|
mark_safeloc1:
|
||||||
|
mov [0xDEADBEEF],eax #write a pointer to safe location (usually after this)
|
||||||
|
pop eax
|
||||||
|
pushfd
|
||||||
|
inc eax #skip one instruction
|
||||||
|
popfd
|
||||||
|
push eax
|
||||||
|
mark_safeloc2:
|
||||||
|
mov eax,[0xDEADBEEF] #write a pointer to safe location (same as above)
|
||||||
|
ret
|
Loading…
Reference in New Issue