Let's share some idc we find useful while reverse engineering.
I'll start with this simple IDC that finds all the un-explored STMFD and converts them to code
#include <idc.idc>
static main(void)
{
auto addr = 0xFF0C0000;
auto dis;
while(1) {
addr = FindUnexplored(addr,SEARCH_DOWN);
MakeCode(addr);
dis = GetDisasm(addr);
if(strstr(dis,"STMFD") == 0) {
print("#############");
print(addr);
print(dis);
print("#############");
} else {
MakeUnkn(addr, DOUNK_EXPAND);
}
if(addr > 0xFF7EDFAC) {
break;
}
}
}
engio_writes.idc: select first entry of the list passed to engio_writes (that one with a list of registers and their values)
and it will put a readable comment at the first entry. this comment will show up whenever this memory location is referenced.
#include <idc.idc>
static main()
{
auto counter,reg,val,address,base_address;
auto comment = "";
base_address = ScreenEA();
address = base_address;
for(counter=0;counter<128;counter++)
{
reg = Dword(address);
val = Dword(address+4);
if (reg == 0xFFFFFFFF)
{
MakeDword(address);
MakeDword(address+4);
MakeRptCmt(base_address, comment);
return;
}
if (((reg & 0xFFF00000) != 0xC0F00000) && ((reg & 0xFFF00000) != 0xC0200000))
{
Message("Invalid register: 0x%08X", reg);
return;
}
MakeDword(address);
MakeDword(address+4);
address = address + 8;
comment = sprintf("%s\r\n[0x%08X] <- [0x%08X]", comment, reg, val);
}
}
This one should automatically name most of the the FC_ functions in the firmware, you can easily change it to name FM_ calls too.
#include <idc.idc>
static main(void)
{
auto start_addr = ScreenEA();
auto addr;
auto space_addr;
auto dis,name,str_ptr, possible_name, func_start, response;
response = 0;
while(1) {
Message("Looking @ %x\n", start_addr);
addr = FindText(start_addr,SEARCH_DOWN|SEARCH_NEXT|SEARCH_REGEX, 0, 0, "FC_");
dis = GetDisasm(addr);
if ( addr == BADADDR )
break;
if(strstr(dis,"ADR") == 0) {
str_ptr = GetOperandValue(addr,1);
possible_name = GetString(str_ptr, -1, ASCSTR_C);
space_addr = strstr(possible_name," ");
possible_name = substr(possible_name, 0, space_addr);
//Message("%s\n", possible_name);
name = GetFunctionName(addr);
if(strlen(name) != 0) {
func_start = LocByName(name);
if(addr - func_start < 32 && strstr(name,"sub_") == 0) {
Jump(func_start);
Message("Renaming %s to %s @ %x", name, possible_name + "_maybe", func_start);
response = AskYN(0, "OK?");
if(response == 1) {
MakeName(func_start, possible_name + "_maybe");
}
} else {
Message("No sub or too far away: %d \n", addr - func_start);
}
}
} else {
dis = GetDisasm(addr);
Message("No ADR: %s\n", dis);
if(strstr(dis,"DCB")==0) {
addr = addr + strlen(GetString(addr,-1,ASCSTR_C))+1;
}
}
start_addr = addr + 4;
Message("%x <-> %x\n", addr, start_addr);
}
}
if you have RAM functions like the 0x4B0 interrupt handler they often have a lot of references.
these references are due to constant values like 0x4BD that are accidentally treated as offsets into RAM.
using this script you can remove all those references by marking the offending instruction offsets as numbers. (OpNumber)
simply select the first instruction of the function you want to clean up and run the script.
you will have to run it multiple times as it only removes a few of those references (not sure why).
its based on a script i found on OpenRCE (findstrangerefs.idc)
#include <idc.idc>
static main(void)
{
auto ea, f_end, source;
auto offset;
auto f_start = ScreenEA();
f_end = FindFuncEnd(f_start);
ea = NextNotTail(f_start);
while (ea < f_end && ea != BADADDR)
{
for(offset = 0; offset < 4; offset++)
{
auto address = ea + offset;
source = RfirstB0(address);
while (source != BADADDR)
{
if (source < f_start || f_end <= source)
{
Message("strange code ref: %08lx %s from 0x%08X\n", address, Name(ea), source);
OpNumber(source,1);
OpNumber(source,0);
break;
}
source = RnextB0(address, source);
}
source = DfirstB(address);
while (source != BADADDR)
{
if (source < f_start || f_end <= source)
{
Message("strange data ref: %08lx %s from 0x%08X\n", address, Name(ea), source);
OpNumber(source,1);
OpNumber(source,0);
break;
}
source = DnextB(address, source);
}
}
ea = NextNotTail(ea);
}
}
go over a "StateObject" and it will name all states in the state matrix that are unnamed yet and show all transitions etc.
auto state,event,reg,val,address, name_sets;
auto comment = "";
address = ScreenEA();
name_sets = 0;
auto type = GetString(Dword(address), -1, ASCSTR_C);
auto name = GetString(Dword(address + 0x04), -1, ASCSTR_C);
if(type == "StateObject")
{
MakeDword(address + 0x00);
MakeDword(address + 0x04);
MakeDword(address + 0x08);
MakeDword(address + 0x0C);
MakeDword(address + 0x10);
OpOff(address + 0x00, 0, 0);
OpOff(address + 0x04, 0, 0);
OpOff(address + 0x0C, 0, 0);
OpOff(address + 0x10, 0, 0);
MakeRptCmt(address + 0x10, "State Matrix");
auto state_matrix = Dword(address + 0x10);
auto event_count = Dword(address + 0x14);
auto state_count = Dword(address + 0x18);
for(event=0;event<event_count;event++)
{
for(state=0;state<state_count;state++)
{
auto entry = state_matrix + 8 * (event * state_count + state);
auto transition_func = Dword(entry + 0x04);
comment = sprintf("State %02i <- Event %02i (NextState %02i)", state, event, Dword(entry + 0x00));
MakeDword(entry + 0x00);
MakeDword(entry + 0x04);
if(transition_func != 0)
{
comment = comment + " (Transition function)";
OpOff(entry + 0x04, 0, 0);
if(substr(GetFunctionName(transition_func), 0, 4) == "sub_")
{
auto func_name = "";
func_name = sprintf("%s_state_%i_event_%i", name, state, event);
MakeNameEx(transition_func, func_name, SN_NOCHECK);
name_sets++;
}
}
MakeRptCmt(entry + 0x00, comment);
MakeRptCmt(entry + 0x04, "");
}
}
Message("Commented the table of %i states with %i events each. Named %i functions, because they had default names.\n", state_count, event_count, name_sets);
}
else
{
Message("Invalid structure, you have to run this script on a StateObject\n");
}
StateObject snippet was faulty. updated it.
this script outputs a graphml document from the state transitions of an StateObject.
put the console output in a .graphml document and open it with yEd (http://www.yworks.com/de/products_yed_about.html).
then layout graph (hierarchical, with labels)
if you set the function names for the state transitions properly, the edges will show the event id and transition function name.
auto state,event,reg,val,address, name_sets;
auto comment = "";
address = ScreenEA();
name_sets = 0;
auto type = GetString(Dword(address), -1, ASCSTR_C);
auto name = GetString(Dword(address + 0x04), -1, ASCSTR_C);
if(type == "StateObject")
{
auto state_matrix = Dword(address + 0x10);
auto event_count = Dword(address + 0x14);
auto state_count = Dword(address + 0x18);
Message("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:y=\"http://www.yworks.com/xml/graphml\" xmlns:yed=\"http://www.yworks.com/xml/yed/3\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd\">");
Message(" <key for=\"graphml\" id=\"d0\" yfiles.type=\"resources\"/><key for=\"port\" id=\"d1\" yfiles.type=\"portgraphics\"/><key for=\"port\" id=\"d2\" yfiles.type=\"portgeometry\"/> <key for=\"port\" id=\"d3\" yfiles.type=\"portuserdata\"/><key attr.name=\"url\" attr.type=\"string\" for=\"node\" id=\"d4\"/><key attr.name=\"description\" attr.type=\"string\" for=\"node\" id=\"d5\"/><key for=\"node\" id=\"d6\" yfiles.type=\"nodegraphics\"/><key attr.name=\"url\" attr.type=\"string\" for=\"edge\" id=\"d7\"/><key attr.name=\"description\" attr.type=\"string\" for=\"edge\" id=\"d8\"/><key for=\"edge\" id=\"d9\" yfiles.type=\"edgegraphics\"/>");
Message("<graph edgedefault=\"directed\" id=\"G\">");
for(state=0;state<state_count;state++)
{
Message("<node id=\"State%i\">", state);
Message("<data key=\"d6\"><y:ShapeNode><y:NodeLabel alignment=\"center\" autoSizePolicy=\"content\" fontFamily=\"Dialog\" fontSize=\"12\" fontStyle=\"plain\" hasBackgroundColor=\"false\" hasLineColor=\"false\" modelName=\"custom\" textColor=\"#000000\" visible=\"true\">State %i</y:NodeLabel><y:LabelModel><y:Shape type=\"rectangle\"/></y:LabelModel></y:ShapeNode>", state);
Message("</data></node>");
}
for(event=0;event<event_count;event++)
{
for(state=0;state<state_count;state++)
{
auto entry = state_matrix + 8 * (event * state_count + state);
auto transition_func = Dword(entry + 0x04);
auto next_state = Dword(entry + 0x00);
if(transition_func != 0)
{
Message("<edge id=\"s%ie%i\" source=\"State%i\" target=\"State%i\">", state, event, state, next_state);
Message("<data key=\"d9\"><y:PolyLineEdge><y:Path sx=\"0.0\" sy=\"-15.0\" tx=\"-15.0\" ty=\"0.0\"><y:Point x=\"68.5\" y=\"-15.5\"/><y:Point x=\"38.0\" y=\"-15.5\"/><y:Point x=\"38.0\" y=\"15.0\"/></y:Path><y:LineStyle color=\"#000000\" type=\"line\" width=\"1.0\"/><y:Arrows source=\"none\" target=\"delta\"/><y:EdgeLabel alignment=\"center\" configuration=\"AutoFlippingLabel\" distance=\"2.0\" fontFamily=\"Dialog\" fontSize=\"12\" fontStyle=\"plain\" hasBackgroundColor=\"false\" hasLineColor=\"false\" height=\"18.701171875\" modelName=\"custom\" preferredPlacement=\"anywhere\" ratio=\"0.5\" textColor=\"#000000\" visible=\"true\" width=\"48.6953125\" x=\"5.65234375\" y=\"-20.945312500000007\">[%i] %s", event, GetFunctionName(transition_func));
Message("<y:LabelModel><y:SmartEdgeLabelModel autoRotationEnabled=\"false\" defaultAngle=\"0.0\" defaultDistance=\"10.0\"/></y:LabelModel><y:ModelParameter><y:SmartEdgeLabelModelParameter angle=\"0.0\" distance=\"30.0\" distanceToCenter=\"true\" position=\"right\" ratio=\"0.5\" segment=\"0\"/></y:ModelParameter><y:PreferredPlacementDescriptor angle=\"0.0\" angleOffsetOnRightSide=\"0\" angleReference=\"absolute\" angleRotationOnRightSide=\"co\" distance=\"-1.0\" frozen=\"true\" placement=\"anywhere\" side=\"anywhere\" sideReference=\"relative_to_edge_flow\"/></y:EdgeLabel><y:BendStyle smoothed=\"true\"/></y:PolyLineEdge></data>");
Message("</edge>");
}
}
}
Message("</graph></graphml>\n\n");
}
else
{
Message("Invalid structure, you have to run this script on a StateObject\n");
}
(http://upload.g3gg0.de/pub_files/77dc34ba782c015daac7247186e0dbc9/StateObject.png)
I'm made a function rename script by the register_func.
Basically register_func is using function name to 1st argument . and 2nd argument is actual function pointer.
so now I have a problem to comvert &sub_xxxx in this script.(Thanks nanomad. this is based on your script)
sub_xxx is successfully comverted., but &sub_xxx is not successfully get correct function address by GetOperandValue...
Do you know how can I do that?
GetTypesomething(addr16) ????
auto start_addr = MinEA();
auto addr;
auto func;
auto func_name;
auto addr16;
auto dis,name,str_ptr, possible_name, func_start, response;
response = 0;
while(1) {
Message("Looking from %x\n", start_addr);
addr = FindText(start_addr,SEARCH_DOWN|SEARCH_NEXT|SEARCH_REGEX, 0, 0, "register_func");
dis = GetDisasm(addr);
if ( addr == BADADDR )
break;
if(strstr(dis,"BL") == 0) {
str_ptr = GetOperandValue(addr-4,1);
possible_name = GetString(str_ptr, -1, ASCSTR_C);
if(strlen(possible_name) == 0){
start_addr = addr + 4;
continue;
}
Message(" %s\n", possible_name);
addr16 = addr-8;
addr16 = addr16-4;
func = GetOperandValue(addr16,1);
dis = GetDisasm(addr16);
Message(" %s\n", dis);
func_name = GetFunctionName(func);
Message(" %s\n", func_name);
//check func_name length
if(strlen(func_name) ==0){
Message(" Can't get func_name\n");
start_addr = addr + 4;
continue;
}
//check func_name already comverted
if(strstr(func_name,"sub_") != 0){
Message(" Already comverted\n");
start_addr = addr + 4;
continue;
}
MakeName(func, possible_name);
Message("Converted %s to %s\n", func_name, possible_name);
}
start_addr = addr + 4;
}
Sorry solved myself.
auto start_addr = MinEA();
auto addr;
auto func;
auto func_name;
auto addr16;
auto optype;
auto equal_addr;
auto dis,name,str_ptr, possible_name, func_start, response;
response = 0;
while(1) {
Message("Looking from %x\n", start_addr);
addr = FindText(start_addr,SEARCH_DOWN|SEARCH_NEXT|SEARCH_REGEX, 0, 0, "register_func");
dis = GetDisasm(addr);
if ( addr == BADADDR )
break;
if(strstr(dis,"BL") == 0) {
str_ptr = GetOperandValue(addr-4,1);
possible_name = GetString(str_ptr, -1, ASCSTR_C);
if(strlen(possible_name) == 0){
start_addr = addr + 4;
continue;
}
Message(" %s\n", possible_name);
addr16 = addr-8;
addr16 = addr16-4;
optype = GetOpType(addr16,1);
dis = GetDisasm(addr16);
Message(" %s %d\n", dis,optype);
if(optype==2){
func_name = GetOpnd(addr16,1);
func_name = substr(func_name, 1, strlen(func_name));
Message(" %s", func_name);
}else{
func = GetOperandValue(addr16,1);
func_name = GetFunctionName(func);
}
Message(" %s\n",func_name);
//check func_name length
if(strlen(func_name) ==0){
Message(" Can't get func_name\n");
start_addr = addr + 4;
continue;
}
//check func_name already comverted
if(strstr(func_name,"sub_") != 0){
Message(" Already comverted\n");
start_addr = addr + 4;
continue;
}
MakeName(func, possible_name);
Message("Converted %s to %s\n", func_name, possible_name);
}
start_addr = addr + 4;
}
Possible to port some of the arm console stuff to ida? Like the robo naming script and the decompiler?
I made a small python code which will guess func name from IDA decompiled text.
Currently only phase one guessing method implemented.
this code automatically guess funcname and output a IDA script.
Current result is
Total func converted = 1258/18275
python code is
# coding=utf-8
import sys
import re
argvs = sys.argv
argc = len(argvs)
def parseDryDbgMsg(strFname,strCode,dicParams):
lstCode1 = strCode.split('"')
if(len(lstCode1) < 2):
return ""
strRet = ""
lstRet = []
lstCode = lstCode1[1].split(" ")
#parse all lines
for strT in lstCode:
if(len(strT) == 0): continue;
if(re.match('.*\\%',strT) != None): continue;
if(re.match(":",strT) != None): continue;
if(re.match("<-",strT) != None): continue;
if(re.match("->",strT) != None): continue;
if(re.match("ERR",strT) != None): continue;
if(re.match("#",strT) != None): continue;
if(re.match("!",strT) != None): continue;
if(re.match("=",strT) != None): continue;
if(re.match("\\(",strT) != None): continue;
if(re.match("\\)",strT) != None): continue;
if(re.match("^.*\\.c",strT) != None): continue;
if(re.match("Unknown",strT) != None): continue;
if(re.match(">",strT) != None): continue;
if(re.match("<",strT) != None): continue;
if(re.match("\\+",strT) != None): continue;
if(re.match("\\@",strT) != None): continue;
if(re.match("\\\n",strT) != None): continue;
strT = re.sub("\\*+","",strT)
strT = re.sub(":","",strT)
strT = re.sub("\\(","",strT)
strT = re.sub("\\)","",strT)
strT = re.sub("\\.+","",strT)
strT = re.sub("\\,","",strT)
strT = re.sub("-+","",strT)
strT = re.sub("\\[","",strT)
# print strT
if(len(strT)):
if(re.search("]",strT) != None):
strT = re.sub("]","_",strT);
strRet = strRet + strT
else:
strRet = strRet + strT
strRet = strRet + " ";
#parse result
lstRet = strRet.split(" ")
for strParam in lstRet:
if(len(strParam)):
if strParam in dicParams:
dicParams[strParam] = dicParams[strParam] + 1
# print "%s %s " % (dicParams[strParam],strParam)
else:
dicParams[strParam] = 1;
def PrepareFuncCode(lstFuncCode):
#get original funcname
lstLine = lstFuncCode[0].split('(');
strFname = re.sub("^.* ","",lstLine[0])
if(len(strFname) == 0): return
# print strFname
dicParams = {}
for strCode in lstFuncCode:
if(strCode.find('DryosDebugMsg') != -1):
parseDryDbgMsg(strFname,strCode,dicParams);
#find most counted key
strNFname = "";
intCount = 0;
for k, v in dicParams.items():
if(intCount < v):
strNFname = k
intCount = v
if(len(strNFname) < 8):
return
# print "%s %s " % (dicParams[strNFname],strNFname)
#Dsiplay result
if(intCount > 1):
print "MakeName(%s,%s);" % (strFname,strNFname)
return 1
return 0
def main(argvs,argc):
intFuncnum = 0
intPrevfuncnum = 0
lstFunc = list()
strFname = ""
intConvNum = 0;
#read lines
for strLine in open(argvs[1], 'r'):
#Split each funcs
if(strLine.find("//----- ") != -1):
intFuncnum = intFuncnum + 1
if(intPrevfuncnum < intFuncnum): #enter newfunc
if(len(lstFunc)):
# print lstFunc
if(PrepareFuncCode(lstFunc)):
intConvNum = intConvNum + 1
del lstFunc[:]
bFirstLine = 1
intPrevfuncnum = intFuncnum
else:
if(intFuncnum >=1):
lstFunc.append(strLine)
print "Total func converted = %d/%d" % (intConvNum,intFuncnum)
main(argvs,argc)
Updated . save here for me.
about 3000 funcstions guessed now.
Usage: python ./main.py disasm.c | sort | uniq
Modified
on 6D DryosDebugMessage is moved to RAM space. so you may change a search key from DryosDebugMessage to v67C8
Updated func-guess by register_func .
Previously, not actually convert names.
MakeFunction to STMFD.
When I use CHDK.idc , nanomad's script not working. Because almost STMFD section is already done with MakeCode.
But It's not set a function styles (Keyboard shortcut p). So this script will automachically find STMFD , and MakeFunction those codes.
auto sb = MinEA();
auto se = MaxEA();
auto a, c, w, d;
auto nexf;
c = 0;
for (a=sb; a<se; a=a+4) {
w = Word(a-2);
d = Word(a+2);
//0xBDE8
if ((d==0xE92D) && (w == 0xE8BD) && !strlen(GetFunctionName(a))) {
MakeFunction(a,BADADDR);
Message("MakeFunc %x %s\n",a, GetFunctionName(a));
c = c+1;
}
}
I used to do that, but then I realized you should also check if the prev instruction is code or not beacuse some functions actually mangle the registers before calling STMFD
You can try to port these (or just use them to save an IDC):
https://github.com/alexdu/ARM-console/blob/master/scripts/guessfunc.py
http://a1ex.magiclantern.fm/bleeding-edge/name_funcx.py
Problem is getting the ram segment into arm console along with FW. When I run name funcs and make an IDC it gets all confused since ram segment wasn't loaded at the same time.
nanomad:
Yes correct! I know this problem but it's not so big problem, I think . So just *now* I'm not supported it.
Do you have a problem on your environment?
I'm checking prev instruction with word(addr -4). Does not enouth?
A1ex:
Thanks for pointing this . But IDA script is really inconvinience. So I need to learn IDA python first.
1%:
Yes I know it. IDA script is not supported bigger size of split segment current code. THe "for" function is not working....
Oh, Alex you already have simmuler codes.
name_funcx.py is really simmuler with my work. And I think it's a more better with mine.
Anyway, try to port it. but IDA script has no dictionaly...
Quote from: a1ex on April 15, 2013, 10:04:34 AM
You can try to port these (or just use them to save an IDC):
https://github.com/alexdu/ARM-console/blob/master/scripts/guessfunc.py
http://a1ex.magiclantern.fm/bleeding-edge/name_funcx.py
You can use the IDA python interface ;)
Lesson1 IDA python version of my function-nized by STMFD.(lol
from idaapi import *
# Get current ea
adStea = MinEA()
adEdea = MaxEA()
intCount = 0;
for ad in range(adStea,adEdea,4):
insPre = get_word(ad-2)
insCur = get_word(ad+2)
strFname = ""
strFname = get_func_name(ad)
if((insCur==0xE92D) and (insPre==0xE8BD) and not (strFname==None)):
MakeFunction(ad,BADADDR);
print "MakeFunc %x %s\n" % (ad, strFname)
intCount = intCount + 1
print "TotalCount=%d\n" % intCount
nanomad's script can also name PD functions
code added on bitbacket
https://bitbucket.org/minimimi/ml-idc/src/d6d5e1c6b918cada4a828c54bfd592a04f374078/ml.py?at=default
How to use it.
1: Get and use CHDK.idc and related files.
2: ml.py from IDA menu (File -> script file)
This script is now supporting MakeFunc by STMFD and MakeName by register_func
change log
- [STMFD] added nanomad's suggestion related codes
ported Alex's method 1. But something wrong.....
https://bitbucket.org/minimimi/ml-idc/src/
porting from Alex's method 2. and solved some valiable bug in method 1
Added new method by me.
The subroutine which is only Get/Set memory to naming [SG]etVal_v(Memory Address)
ex:
SetVal_v80c90()
GetVal_v80c90()
Maybe we can have the script name state objects/event managers/etc. In the funtions where they initialize there is usually an address of where the return ends up.
This way its not just dword_sjdflfj
Quote from: 1% on April 21, 2013, 09:52:51 PM
Maybe we can have the script name state objects/event managers/etc. In the funtions where they initialize there is usually an address of where the return ends up.
This way its not just dword_sjdflfj
hmm, Now I confusing in Alex's method4 ,,,, I will try to make it when I finish it. But I can't understand what you need...
Also I want to mearge g3gg and nanomads script If I can.
Anyway, current code is multiple segment supported . Try it if you interested in it.
Running on all bins now... for the ram segment it would be good if script jumped back to rom and got the name from there.. ramsub+ramoffset = sub in main rom. Naming strings might not be in the copied ram portion.
First, I would like to say solved one importand bug in new_name() in my script.
Previous script cant named by Alex's method1.
Quote from: 1% on May 02, 2013, 09:20:23 PM
Running on all bins now... for the ram segment it would be good if script jumped back to rom and got the name from there.. ramsub+ramoffset = sub in main rom. Naming strings might not be in the copied ram portion.
Let me confirm , that is we need to copy names from ROM to RAM, right?
Because some funcs are copyed from ROM to RAM. Is this a correct understanding?
this snippet searches for all functions in the binary and searches for pointers to this function.
set "findall" to 0 to just find pointers to current offset.
thinking about how to make both features accessible easily. hotkeys?
warning: 'findall' runs several minutes
#include <idc.idc>
static find_dword(addr, start, end)
{
auto addr_str = sprintf("%02X %02X %02X %02X", addr & 0xFF, (addr >> 8) & 0xFF, (addr >> 16) & 0xFF, (addr >> 24) & 0xFF);
auto location = start;
Message(" [i] Searching DWORD: %s\n", addr_str);
do
{
location = FindBinary(location, SEARCH_DOWN | SEARCH_CASE, addr_str);
if(location == BADADDR || location > end || location < start)
{
return;
}
if((location % 4) == 0)
{
Message(" [i] Found at 0x%08X\n", location);
MakeDword(location);
OpOff(location, -1, 0);
location = location + 4;
}
else
{
location = location + 1;
}
} while(1);
}
static main()
{
auto findall = 1;
auto pos = ScreenEA();
auto segment_start = GetSegmentAttr(pos, SEGATTR_START);
auto segment_end = GetSegmentAttr(pos, SEGATTR_END);
Message("-----------------\n");
if(findall)
{
pos = segment_start;
do
{
Message(" [i] Scanning in 0x%08X-0x%08X\n", segment_start, segment_end);
find_dword(pos, segment_start, segment_end);
pos = NextFunction(pos);
} while(pos != BADADDR);
}
else
{
Message(" [i] Scanning in 0x%08X-0x%08X\n", segment_start, segment_end);
find_dword(pos, segment_start, segment_end);
}
Message("-----------------\n");
}