home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Mammon_ / idaprimer.txt < prev    next >
Text File  |  2000-05-25  |  64KB  |  1,401 lines

  1.                  Mammon_'s Tales to Fravia's Grandson
  2.                         ...An IDA Primer...
  3.  
  4. Contents
  5. --------
  6. *Introduction
  7. *Configuring IDA
  8. *Loading a program
  9. *Viewing Imports
  10. *Viewing Exports
  11. *Viewing Strings/Resources
  12. *Searching for Strings/Code
  13. *Commenting Code
  14. *Working with IDC scripts
  15. *Producing an Output File
  16. *Advanced Techniques
  17.  
  18. Introduction
  19. ------------
  20. Ok, this is a long document for "the basics", mostly due to the Configuration section. New users may
  21. want to skip this section, or simply apply the changes suggested therein without reading the explanations.
  22. Also, some parts of the "Advanced Techniques" may get lengthy as well.
  23.  
  24. Why is IDA so useful? Because it can do anything. IDA will change the way you think about disassemblers; it
  25. will change the way you think about cracking. W32Dasm? A toy. Soft-Ice? Unnecessary. When you have a disassembler
  26. that lets you follow the flow of execution by tapping the keyboard, backtrace just as easily, name variables/
  27. addresses/functions, view the entire program as opcodes or assembly, change code to data and back again according
  28. to your whim, and even run limited C programs to perform operations on the code from searching and parsing to
  29. translating and patching...why go somewhere else?
  30.  
  31. IDA is a reverse engineer's tool. Like many such tools, it is incredibly useful for crackers...yet it is not
  32. designed for them. It is huge, it is complex, it requires a lot of studying and tuning to get it to perform.
  33. What follows is an attempt to demonstrate how to get the most out of IDA when getting it "straight out of the
  34. box": configuration changes are suggested, macros are provided, and a basic tour of using the program in the
  35. manner of W32Dasm is attempted as well. By the end of this document you should know well IDA's capabilities and
  36. potential; you should also realize how to track down API calls, string references, and specific opcodes.
  37.  
  38. As a tool for engineers, IDA requires that you know what you are doing. The more you know, the more you will get
  39. out of it. At the very least I would recommend reading the PE file format reference at
  40. http://www.microsoft.com/win32dev/base/pefile.htm
  41. Cristina Cifuentes' doctoral thesis (selectively, of course) at
  42. http://www.cs.uq.edu.au/groups/csm/dcc.html#thesis
  43. and of course the IDA home page itself at
  44. http://www.unibest.ru/~ig/index.html
  45. ...That should be enough to get you familiar enough with disassembling and the PE file format to use
  46. IDA to its greatest potential.
  47.  
  48. What are all these IDA files? Yes, IDA is huge, and some of the files may be useless to you. Here is a quick
  49. overview:
  50. *.CFG -- IDA Configuration Settings
  51. IDA.KEY -- Registration File
  52. IDA2.EXE -- OS/2 Executable
  53. IDAX.EXE -- DOS4/GW Executable
  54. IDAW.EXE -- Win32 Executable
  55. IDA.INT -- Auto-generated comments
  56. *.LDO -- File loader for OS/2 Executable (ex PE.LDO = PE File Loader)
  57. *.LDX -- File loader for DOS4/GW Executable
  58. *.LDW -- File loader for Windows Executable
  59. *.DLL -- Disassembler for OS/2 Executable (ex PC.DLL = PC Disassembler)
  60. *.D32 -- Disassembler for DOS4/GW Executable
  61. *.W32 -- Disassembler for Windows Executable
  62. /IDC -- IDC macro scripts and include files
  63. /IDS -- IDS files for commenting/naming imports
  64. /Sig -- FLIRT/Compiler signature files (for recognizing target's compiler)
  65.  
  66.  
  67. Configuring IDA
  68. ---------------
  69. In the \IDA37? directory, locate the file Ida.cfg and open it in any text editor.
  70. The file is divided into two main sections, First Pass and Second Pass, each of
  71. which has different configuration options: the first pass contains the file
  72. extension to processor type associations, the memory and screen configuration,
  73. OS/2 options, and hotkey definitions; the second pass contains general program
  74. parameters, code analysis configuration, format options for the code displayed,
  75. ASCII string display options, displayable characters, macro definitions, and
  76. processor options.
  77.  
  78. The areas of the configuration file that you will most likely want to change are:
  79. *Screen Configuration
  80. *Format Options (Text Representation)
  81. *ASCII Display Options
  82. *Processor Options
  83.  
  84. Some additional areas that you may want to configure are:
  85. *Hotkey Definitions
  86. *Code Analysis Options
  87. *Displayable Characters
  88.  
  89. 1. Screen Configuration
  90. Out of the box, the IDA screen configuration section looks like this:
  91. ====================================================================
  92. //    Screen configuration (first pass)
  93. //    ---------------------------------
  94. #ifdef __MSDOS__
  95. SCREEN_MODE        = 0        // Screen mode to use
  96.                     // 0 - don't change screen mode
  97.                     // DOS: AL for INT 10
  98. #else
  99. SCREEN_MODE        = 0        // Screen mode to use
  100.                     // high byte - cols, low byte - rows
  101.                     // i.e. 0x5020 is 80cols, 32rows
  102. #endif
  103. SCREEN_PALETTE        = 0        // Screen palette:
  104.                     // 0 - automatic
  105.                     // 1 - B & W
  106.                     // 2 - Monochrone
  107.                     // 3 - Color
  108. ====================================================================
  109. The MD-DOS SCREEN_MODE anf the SCREEN_PALETTE need not change. If you are using
  110. Windows, the second ("else) SCREEN_MODE will determine your screen size. Note that
  111. the col/row numbers are in hexadecimal, thus 0x5020 is 80x32 in decimal. I have found
  112. that  0x5530 works best on an 800x600 resolution screen.
  113.  
  114. 2. Text Representation
  115. Initially, the Text Representation section is given as follows:
  116. ====================================================================
  117. //    Text representation
  118. //-------------------------------------------------------------------------
  119. OPCODE_BYTES           = 0            // don't display bytes of instruction/data
  120. INDENTION            = 16        // Indention of instructions
  121. COMMENTS_INDENTION    = 40        // Indention for on-line comments
  122. MAX_TAIL            = 16        // Tail depth
  123. MAX_XREF_LENGTH        = 80        // Maximal length of line with cross-references
  124. MAX_DATALINE_LENGTH    = 70        // Data directives (db,dw, etc):
  125.                                 //   max length of argument string
  126. SHOW_AUTOCOMMENTS    = NO        // Don't show silly comments
  127. SHOW_BAD_INSTRUCTIONS    = NO        // Don't bother about instruction lengthes
  128. SHOW_BORDERS        = YES        // Borders between data/code
  129. SHOW_EMPTYLINES        = YES        // Generate empty line to make
  130.                                 // text more readable
  131. SHOW_LINEPREFIXES    = YES        // Show line prefixes (1000:0000)
  132. SHOW_SEGMENTS        = YES        // Show segments in addresses
  133. USE_SEGMENT_NAMES    = YES        // Show segment names instead of numbers
  134. SHOW_REPEATABLE_COMMENTS = YES    // Of course, use repeatable comments
  135.                                 // Disabling this increases IDA speed.
  136. SHOW_VOIDS        = NO            // Don't display <void> marks
  137. SHOW_XREFS        = 2                // Show 2 cross-references
  138. SHOW_XREF_VALUES    = YES        // If not, xrefs are displayed
  139.                                  // as "..."
  140. SHOW_SEGXREFS        = YES        // Show segment part of addresses
  141.                                 // in cross-references
  142. SHOW_SOURCE_LINNUM    = YES        // Show source line numbers
  143.                                 // (used in .obj files and java)
  144. SHOW_ASSUMES        = YES        // Generate 'assume' directives
  145. SHOW_ORIGINS        = YES        // Generate 'org' directives
  146. USE_TABULATION        = YES        // Use '\t' in output file
  147. ====================================================================
  148. Of course this section is modified to suit taste, and can be configured through the
  149. Options-Text Representation menu item (though changes made within IDA are saved only
  150. for the current project). I usually use the following changes:
  151. ====================================================================
  152. OPCODE_BYTES           = 6        // I want the hex codes!
  153. INDENTION            = 0        // Save some space
  154. COMMENTS_INDENTION    = 30    // Save some space
  155. MAX_DATALINE_LENGTH    = 100    // These can get long
  156. SHOW_BAD_INSTRUCTIONS    = YES    // bother about instruction lengthes
  157. SHOW_BORDERS        = NO        // why border?
  158. SHOW_EMPTYLINES        = NO        // These lines waste space
  159. SHOW_XREFS            = 15        // Show a ton of  cross-references
  160. SHOW_ORIGINS        = NO        // Hide 'org' directives
  161. ====================================================================
  162.  
  163. 3. ASCII Strings & Names
  164. Here are the default settings that come with IDA:
  165. ====================================================================
  166. //    ASCII strings & names
  167. //-------------------------------------------------------------------------
  168. ASCII_GENNAMES        = YES        // Generate names when making
  169.                     // an ASCII string
  170. ASCII_TYPE_AUTO        = YES        // Should IDA mark generated ascii names
  171.                     // as 'autogenerated'?
  172.                     // Autogenerated names will be deleted
  173.                     // when the ascii string is deleted
  174.                     // Also, they are displayed with the
  175.                     // same color as dummy names.
  176. ASCII_LINEBREAK        = '\n'        // This char forces IDA
  177.                     // to start a new line
  178. ASCII_PREFIX        = "a"        // This prefix is used when a new
  179.                     // name is generated
  180. #define ASCII_STYLE_C        0x00000000// Character-terminated ASCII string
  181. #define ASCII_STYLE_PASCAL    0x00000001// Pascal-style ASCII string (length byte)
  182. #define ASCII_STYLE_LEN2    0x00000002// Pascal-style, length has 2 bytes
  183. #define ASCII_STYLE_UNICODE    0x00000003// Unicode string
  184. ASCII_STYLE             = ASCII_STYLE_C // Default is C-style
  185. ASCII_SERIAL        = NO        // Serial names are disabled
  186. ASCII_SERNUM        = 0        // Number to start serial names
  187. ASCII_ZEROES        = 0        // Number of leading zeroes in
  188.                     // serial names
  189.     // type of generated names: (dummy names)
  190. #define NM_REL_OFF    0
  191. #define NM_PTR_OFF    1
  192. #define NM_NAM_OFF    2
  193. #define NM_REL_EA    3
  194. #define NM_PTR_EA    4
  195. #define NM_NAM_EA    5
  196. #define NM_EA        6
  197. #define NM_EA4        7
  198. #define NM_EA8        8
  199. #define NM_SHORT    9
  200. #define NM_SERIAL    10
  201. DUMMY_NAMES_TYPE    = NM_REL_OFF
  202. MAX_NAMES_LENGTH    = 15        // Maximal length of new names
  203.                     // (you may specify values up to 120)
  204. // Types of names that should be included into the list of names
  205. // (this list usually appears by pressing Ctrl-L)
  206. //    normal      1
  207. //    public      2
  208. //    auto      4
  209. //    weak      8
  210. LIST_NAMES        = 0x07    // default: include normal, public, weak
  211. ...and a ton of demangling info...
  212. ====================================================================
  213. What's the big deal? It's only strings... Well, to tell the truth, a string is just
  214. a collection of bytes virtually indistinguishable--to the untrained eye--from opcode
  215. bytes. IDA will pick up a lot of strings, but it has to have a default string type...
  216. hence the ASCII_STYLE definition. This defaults to ASCII_STYLE_C, but you may want to
  217. change it to ASCII_STYLE__UNICODE if you will be dealing primarily with Windows 95/NT
  218. programs. [Note: You can change string types dynamically in IDA using the Options->ASCII
  219. Strings Style menu item, in case your target has multiple string types...notice also that
  220. from within IDA you can define different "end characters" from 1 to 2 bytes...this is very
  221. handy for special "internal" data types that some targets use.]
  222. Now, what about those weird name types? Here they are, translated:
  223. //    normal      1: this shows internal functions, etc
  224. //    public      2: this includes exports, entry points
  225. //    auto      4: this shows the irritating IDA names
  226. //    weak      8: this is useless ;)
  227. #define NM_REL_OFF    0 = loc_0_1234     segbase relative to prog base & offset from segbase
  228. #define NM_PTR_OFF    1 = loc_1000_1234  segment base address & offset from the segment base
  229. #define NM_NAM_OFF    2 = loc_dseg_1234  (*) segment name & offset from the segment base
  230. #define NM_REL_EA    3 = loc_0_11234    segment relative to base address & full address
  231. #define NM_PTR_EA    4 = loc_1000_11234 segment base address & full address
  232. #define NM_NAM_EA    5 = loc_dseg_11234 segment name & full address
  233. #define NM_EA        6 = loc_12         full address (no leading zeroes)
  234. #define NM_EA4        7 = loc_0012       full address (at least 4 digits)
  235. #define NM_EA8        8 = loc_00000012   full address (at least 8 digits)
  236. #define NM_SHORT    9 = dseg_1234      the same as (*) without data type specifier
  237. #define NM_SERIAL    10= loc_1          enumerated names (1,2,3...
  238.  
  239. The first part determines what names are shown in the "Names" window; in general, the fewer the better.
  240. If you want the Names to show only the exports of the program, choose 0x02. The next section determines
  241. how internal addresses are referred to in the disassembled listing; if you like Sourcer's method
  242. of defining "location1, location2, etc" you should try defaulting to NM_SERIAL; if you like the location
  243. to show just the segment name and offset, use NM_SHORT. You can experiment with this using the Options->
  244. Name Representation menu item in IDA.
  245.  
  246. I tend to set the following parameters:
  247. ASCII_TYPE_AUTO        = NO
  248. ASCII_PREFIX        = "str->"
  249. MAX_NAMES_LENGTH    = 15
  250. LIST_NAMES        = 0x03
  251. DUMMY_NAMES_TYPE    = NM_SHORT
  252. **Note to use my "str->" prefix you will have to change the following line
  253. NameChars =     "$?@"        // asm specific character
  254. to
  255. NameChars =    "$?@->"        // asm specific character
  256. ...see #7 below. This setup will fill the Names window with strings, exports, and imports.
  257.  
  258. 4. Processor Specific Parameters
  259. The PC-specific parameters for IDA are given as follows:
  260. ====================================================================
  261. #ifdef __PC__                // INTEL 80x86 PROCESSORS
  262. USE_FPP            = YES
  263.                     // Floating Point Processor
  264.                     // instructions are enabled
  265. WINDIR            = "c:\\windows"    // Default directory to look up for
  266.                     // DLL files
  267. OS2DIR            = "c:\\os2"    // OS/2 main directory (is used to
  268.                     // look up DLLs)
  269. // IBM PC specific analyser options
  270. PC_ANALYSE_PUSH        = YES        // Convert immediate operand of "push" to offset
  271.                     //     In sequence
  272.                     //         push    seg
  273.                     //         push    num
  274.                     //     IDA will try to convert <num> to offset.
  275. PC_ANALYSE_NOP        = YES        // Convert db 90h after "jmp" to "nop"
  276.                     //     Sequence
  277.                     //         jmp    short label
  278.                     //         db    90h
  279.                     //     will be converted to
  280.                     //         jmp    short label
  281.                     //         nop
  282. PC_ANALYSE_MOVOFF    = YES        // Convert immediate operand of "mov reg,..." to offset
  283.                     //     In sequence
  284.                     //         mov reg,    num
  285.                     //         mov segreg, immseg
  286.                     //      where
  287.                     //       reg    - any general register
  288.                     //       num    - a number
  289.                     //       segreg - any segment register
  290.                     //       immseg - any form of operand representing a segment paragraph
  291.                     //     <num> will be converted to an offset
  292. PC_ANALYSE_MOVOFF2    = YES        // Convert immediate operand of "mov memory,..." to offset
  293.                     //     In sequence
  294.                     //         mov x1, num
  295.                     //         mov x2, seg
  296.                     //      where
  297.                     //         x1,x2 - any references to memory
  298.                     //     <num> will be converted to an offset
  299. // translation used to build an ASCII string name by its contents
  300. // (now it is tuned for 866 codepage)
  301. // the order and number of the string constants is important!
  302.  
  303. ... a bunch of XLat stuff...
  304.  
  305. #endif // __PC__
  306. ====================================================================
  307. As you can, see, there are a few useful disassembly options here, most of which
  308. are already set. In fact, the only thing you should have to change is the following
  309. line:
  310. WINDIR            = "c:\\windows\\system"
  311. This will correctly locate the WinAPI DLLs--it is very important to set this!
  312.  
  313. 5. Keyboard HotKey Definitions
  314. This section is mostly a matter of personal taste, but I thought that I would draw attention to it.
  315. Here are the default keyboard shortcuts (you may want to print this out):
  316. "LoadFile"        =    0        // Load additional file into database
  317. "LoadIdsFile"        =    0        // Load IDS file
  318. "LoadDbgFile"        =    0        // Load DBG file
  319. "LoadSigFile"        =    0        // Load SIG file
  320. "Execute"        =    "F2"        // Execute IDC file
  321. "ExecuteLine"        =    "Shift-F2"    // Execute IDC line
  322. "Shell"            =    "Alt-Z"
  323. "About"            =    0
  324. "SaveBase"        =    "Ctrl-W"
  325. "SaveBaseAs"        =    0
  326. "Abort"            =    0        // Abort IDA, don't save changes
  327. "Quit"            =    "Alt-X"        // Quit to DOS, save changes
  328. "ProduceMap"        =    "Shift-F10"    // Produce MAP file
  329. "ProduceAsm"        =    "Alt-F10"
  330. "ProduceLst"        =    0
  331. "ProduceExe"        =    "Ctrl-F10"
  332. "ProduceDiff"        =    0        // Generate difference file
  333. "DumpDatabase"        =    0        // Dump database to IDC file
  334. "EditFile"        =    0        // Small text editor
  335. "JumpAsk"        =    'G'
  336. "JumpName"        =    "Ctrl-L"
  337. "JumpSegment"        =    "Ctrl-S"
  338. "JumpSegmentRegister"    =    "Ctrl-G"
  339. "JumpQ"            =    "Ctrl-Q"
  340. "JumpPosition"        =    "Ctrl-M"
  341. "JumpXref"        =    "Ctrl-X"
  342. "JumpOpXref"        =    "X"
  343. "JumpFunction"        =    "Ctrl-P"
  344. "JumpEntryPoint"    =    "Ctrl-E"
  345. "JumpEnter"        =    "Enter"        // jump to address under cursor
  346. "Return"        =    "Esc"
  347. "UndoReturn"        =    "Ctrl-Enter"    // undo the last Esc
  348. "EmptyStack"        =    0        // make the jumps stack empty
  349. "SetDirection"        =    "Tab"
  350. "MarkPosition"        =    "Alt-M"
  351. "JumpVoid"        =    "Ctrl-V"
  352. "JumpCode"        =    "Ctrl-C"
  353. "JumpData"        =    "Ctrl-D"
  354. "JumpUnknown"        =    "Ctrl-U"
  355. "JumpExplored"        =    "Ctrl-A"
  356. "AskNextImmediate"    =    "Alt-I"
  357. "JumpImmediate"        =    "Ctrl-I"
  358. "AskNextText"        =    "Alt-T"
  359. "JumpText"        =    "Ctrl-T"
  360. "AskBinaryText"        =    "Alt-B"
  361. "JumpBinaryText"    =    "Ctrl-B"
  362. "JumpNotFunction"    =    "Alt-U"
  363. "MakeJumpTable"        =    "Alt-J"
  364. "MakeAlignment"        =    'L'
  365. "MakeCode"         =    'C'
  366. "MakeData"        =    'D'
  367. "MakeAscii"        =    'A'
  368. "MakeArray"        =    '*'
  369. "MakeUnknown"        =    'U'
  370. "MakeVariable"        =    0
  371. "SetAssembler"        =    0
  372. "SetNameType"        =    0
  373. "SetDemangledNames"    =    0
  374. "SetColors"        =    0
  375. "MakeName"        =    'N'
  376. "MakeAnyName"        =    "Ctrl-N"
  377. "ManualOperand"        =    "Alt-F1"
  378. "MakeFunction"        =    'P'
  379. "EditFunction"        =    "Alt-P"
  380. "DelFunction"        =    0
  381. "FunctionEnd"        =    'E'
  382. "OpenStackVariables"    =    "Ctrl-K" // open stack variables window
  383. "ChangeStackPointer"    =    "Alt-K"  // change value of SP
  384. "MakeComment"        =    ':'
  385. "MakeRptCmt"        =    ';'
  386. "MakePredefinedComment"    =    "Shift-F1"
  387. "MakeExtraLineA"    =    "Ins"
  388. "MakeExtraLineB"    =    "Shift-Ins"
  389. "OpNumber"        =    '#'
  390. "OpHex"            =    'Q'
  391. "OpDecimal"        =    'H'
  392. "OpOctal"        =    0
  393. "OpBinary"        =    'B'
  394. "OpChar"        =    'R'
  395. "OpSegment"        =    'S'
  396. "OpOffset"        =    'O'
  397. "OpOffsetCs"        =    "Ctrl-O"
  398. "OpAnyOffset"        =    "Alt-R"
  399. "OpUserOffset"        =    "Ctrl-R"
  400. "OpStructOffset"    =    'T'
  401. "OpStackVariable"    =    'K'
  402. "OpEnum"        =    'M'
  403. "ChangeSign"        =    '-'
  404. "CreateSegment"        =    0
  405. "EditSegment"        =    "Alt-S"
  406. "KillSegment"        =    0
  407. "MoveSegment"        =    0
  408. "SegmentTranslation"    =    0
  409. "SetSegmentRegister"    =    "Alt-G"
  410. "SetSegmentRegisterDefault"    = 0
  411. "ShowRegisters"        =    "Space"
  412. "OpenSegmentRegisters"    =    0    // open various windows:
  413. "OpenSegments"        =    0
  414. "OpenSelectors"        =    0
  415. "OpenNames"        =    0
  416. "OpenXrefs"        =    0
  417. "OpenFunctions"        =    0    // open functions window
  418. "OpenStructures"    =    0    // open structures window
  419. "OpenEnums"        =    0    // open enums window
  420. "OpenSignatures"    =    0    // open signatures window
  421. "PatchByte"        =    0
  422. "PatchWord"        =    0
  423. "Assemble"        =    0
  424. "TextLook"        =    0        // set text representation
  425. "SetAsciiStyle"        =    "Alt-A"        // set ascii strings style
  426. "SetAsciiOptions"    =    0        // set ascii strings options
  427. "SetCrossRefsStyle"    =    0        // set cross-referneces style
  428. "SetDirectives"        =    0        // setup assembler directives
  429. "ToggleDump"        =    "F4"        // show dump or normal view
  430. "SetAuto"        =    0        // background analysis
  431. "ViewFile"        =    0
  432. "Calculate"        =    '?'
  433. "ShowFlags"        =    'F'
  434. "WindowOpen"        =    "F3"
  435. "WindowMove"        =    "Ctrl-F5"
  436. "WindowZoom"        =    "F5"
  437. "WindowPrev"        =    "Shift-F6"
  438. "WindowNext"        =    "F6"
  439. "WindowClose"        =    "Alt-F3"
  440. "WindowTile"        =    "F7"
  441. "WindowCascade"        =    "F8"
  442. "SetProcessor"        =    0
  443. "AddStruct"        =    "Ins"        // add struct type
  444. "DelStruct"        =    "Del"        // del struct type
  445. "ExpandStruct"        =    "Ctrl-E"    // expand struct type
  446. "ShrinkStruct"        =    "Ctrl-S"    // shrink struct type
  447. "MoveStruct"        =    0        // move struct type
  448. "DeclareStructVar"    =    "Alt-Q"        // declare struct variable
  449. "AddEnum"        =    "Ins"        // add enum
  450. "DelEnum"        =    "Del"        // del enum
  451. "EditEnum"        =    "Ctrl-E"    // edit enum
  452. "AddConst"        =    "Ctrl-N"    // add new enum member
  453. "EditConst"        =    'N'        // edit enum member
  454. "DelConst"        =    'U'        // delete enum member
  455.  
  456. Quite a few, eh? Basically, anything in IDA can have a hotkey. Note all of the 0's in the
  457. above list: these options have not hotkeys by default. It is generally good to set frequently-
  458. use operations (ASCII text representation, View Names, Search, etc) up as HotKeys, and to change
  459. hotkeys which make no sense into better menmonics.
  460.  
  461. 6. Analysis Parameters
  462. IDA by default has the following Anaylsis Parameters set:
  463. //    Analysis parameters
  464. //-------------------------------------------------------------------------
  465. ENABLE_ANALYSIS        = YES    // Background analysis is enabled
  466. SHOW_INDICATOR        = YES    // Show background analysis indicator
  467. #define AF_FIXUP    0x0001    // Create offsets and segments using fixup info
  468. #define AF_MARKCODE    0x0002    // Mark typical code sequences as code
  469. #define AF_UNK        0x0004    // Delete instructions with no xrefs
  470. #define AF_CODE        0x0008    // Trace execution flow
  471. #define AF_PROC        0x0010    // Create functions if call is present
  472. #define AF_USED        0x0020    // Analyse and create all xrefs
  473. #define AF_FLIRT    0x0040    // Use flirt signatures
  474. #define AF_PROCPTR    0x0080    // Create function if data xref data->code32 exists
  475. #define AF_JFUNC    0x0100    // Rename jump functions as j_...
  476. #define AF_NULLSUB    0x0200    // Rename empty functions as nullsub_...
  477. #define AF_LVAR        0x0400    // Create stack variables
  478. #define AF_TRACE    0x0800    // Trace stack pointer
  479. #define AF_ASCII    0x1000    // Create ascii string if data xref exists
  480. #define AF_IMMOFF    0x2000    // Convert 32bit instruction operand to offset
  481. #define AF_DREFOFF    0x4000    // Create offset if data xref to seg32 exists
  482. #define AF_FINAL    0x8000    // Final pass of analysis
  483.                 // See also ANALYSIS2, bit AF2_DODATA
  484. ANALYSIS    = 0xFFFF    // This value is combination of the defined
  485.                 // above bits.
  486. #define AF2_JUMPTBL    0x0001    // Locate and create jump tables
  487. #define AF2_DODATA    0x0002    // Coagulate data segs in the final pass
  488. ANALYSIS2    = 0x0001
  489. ====================================================================
  490. Generally, you will not need to change any of these parameters. In case you feel
  491. like playing with them, though, here is the IDA help file description of each:
  492.  
  493. Create offsets and segments using fixup info
  494.         IDA will use relocation information to make the disassembly
  495.         nicer. In particular, it will convert all data items with
  496.         relocation information to words or dwords like this:
  497.                 dd offset label
  498.                 dw seg seg000
  499.         If an instruction has a relocation information attached to it,
  500.         IDA will convert its immediate operand to an offset or segment:
  501.                 mov     eax, offset label
  502.         You can display the relocation information attached to the current
  503.         item by using show @0:953[internal] flags command.
  504. Mark typical code sequences as code
  505.         IDA knows some typical code sequences for each processor.
  506.         For example, it knows about typical sequence
  507.                 push    bp
  508.                 mov     bp, sp
  509.         If this option is enabled, IDA will search for all typical sequences
  510.         and convert them to instructions even if there are no references
  511.         to them. The search is performed at the loading time.
  512. Delete instructions with no xrefs
  513.         This option allows IDA to undefine unreferences instructions.
  514.         For example, if you @0:914[undefine] an instruction at the start of a
  515.         function, IDA will trace execution flow and delete all instructions
  516.         that lose references to them.
  517. Trace execution flow
  518.         This options allows IDA to trace execution flow and convert all
  519.         references bytes to @0:916[instructions].
  520. Create functions if call is present
  521.         This options allows IDA to create @0:933[function] (proc) if a call
  522.         instruction is present. For example, the presence of:
  523.                 call loc_1234
  524.         leads to creation of a function at label loc_1234
  525. Analyse and create all xrefs
  526.         Without this option IDA will not thoroughly analyse the program.
  527.         If this option is disabled, IDA will simply trace execution flow,
  528.         nothing more (no xrefs, no additional checks, etc)
  529. Use flirt signatures
  530.         Allows usage of FLIRT technology
  531. Create function if data xref data->code32 exists
  532.         If IDA encounters a data references from DATA segment to 32bit
  533.         CODE segment, it will check for the presence of meaningful
  534.         (disassemblable) instruction at the target. If there is an
  535.         instruction, it will mark is as an instruction and will create
  536.         a function there.
  537. Rename jump functions as j_...
  538.         This option allows IDA to rename simple functions containing only
  539.                 jmp somewhere
  540.         instruction to "j_somewhere".
  541. Rename empty functions as nullsub_...
  542.         This option allows IDA to rename empty functions containing only
  543.         a "return" instruction as "nullsub_..."
  544.         (... is replaced by a serial number: 0,1,2,3...)
  545. Create stack variables
  546.         This option allows IDA to automatically create stack variables and
  547.         function parameteres.
  548. Trace stack pointer
  549.         This option allows IDA to @0:743[trace] value of SP register.
  550. Create ascii string if data xref exists
  551.         If IDA encounters a data reference to an undefined item, it
  552.         checks for the presence of ASCII string at the target. If the length
  553.         of ASCII string is big enough (more than 4 chars in 16bit or data
  554.         segments; more than 16 chars otherwise), IDA will automatically create
  555.         an @0:918[ASCII] string.
  556. Convert 32bit instruction operand to offset
  557.         This option works only in 32bit segments.
  558.         If an instruction has an immediate operand and the operand
  559.         can be represented as a meaningful offset expression, IDA will
  560.         convert it to an offset. However, the value of immediate operand
  561.         must be higher than 0x10000.
  562. Create offset if data xref to seg32 exists
  563.         If IDA encounters a data reference to 32bit segment and the target
  564.         contains 32bit value which can be represented as an offset expression,
  565.         IDA will convert it to an offset
  566. Make final analysis pass
  567.         This option allows IDA to coagulate all @0:914[unexplored] bytes
  568.         by converting them to data or instructions.
  569. Locate and create jump tables
  570.         This option allows IDA to try to guess address and size of @0:863[jump]
  571.         tables. Please note that disabling this option will not disable
  572.         the recognition of C-style typical switch constructs.
  573. Coagulate data in the final pass
  574.         This option is meaningful only if "Make final analysis pass"
  575.         is enabled. It allows IDA to convert @0:914[unexplored] bytes
  576.         to data arrays in the data segments. If this option is disabled,
  577.         IDA will coagulate only code segments.
  578.  
  579. 7. Character Translations and Allowed Character Lists
  580. The default character rules suppleid with IDA are as follows:
  581. ====================================================================
  582. //    Character translations and allowed character lists
  583. //-------------------------------------------------------------------------
  584. // translation when ASCII string name is built using its contents
  585. XlatAsciiName =
  586. /*00..0F*/ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
  587. /*10..1F*/ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
  588. /*20..3F*/ " !\"# %&'()*+,-_/"
  589.        "0123456789:;<=>?"
  590. /*40..5F*/ "@ABCDEFGHIJKLMNO"
  591.        "PQRSTUVWXYZ[\\]^_"
  592. /*60..7F*/ "`abcdefghijklmno"
  593.        "pqrstuvwxyz{|}~"
  594. /*80..9F*/ "ABVGDEJZIIKLMNOP"
  595.        "RSTUFXCCSS I AUQ"
  596. /*A0..BF*/ "abvgdejziiklmnop"
  597.        "ªªªªªªª++ªª+++++"
  598. /*C0..DF*/ "+--+-+ªª++--ª-+-"
  599.        "---++++++++ª_ªª_"
  600. /*E0..FF*/ "rstufxccss i auq"
  601.        "=▌==()~~▌++vn▌ªá";
  602. // the following characters are allowed in ASCII strings, i.e.
  603. // in order to find end of a string IDA looks for a character
  604. // which doesn't belong to this array:
  605. AsciiStringChars =
  606.     "\r\n\a\v\b\t\x1B"
  607.     " !\"#$%&'()*+,-./0123456789:;<=>?"
  608.     "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
  609.     "`abcdefghijklmnopqrstuvwxyz{|}~"
  610.     "▌nTGSastOdFne8-++µ▌(÷=v· +_óúÑPâ"
  611.     "ßf=·±-¬▌+¼¼++í½+ªªªªªªª++ªª+++++"
  612.     "+--+-+ªª++--ª-+----++++++++ª_ªª_"
  613.     "a_GpSs▌tFTOd8fen";
  614.  
  615. // the following characters are allowed in user-defined names:
  616. NameChars =
  617.     "$?@"        // asm specific character
  618.     "_0123456789"
  619.     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  620.     "abcdefghijklmnopqrstuvwxyz";
  621. // the following characters are allowed in mangled names.
  622. // they will be substituted with the SubstChar during output if names
  623. // are output in a mangled form.
  624. MangleChars = "$:?([.)]"    // watcom
  625.           "@$%?"        // microsoft
  626.           "@$%";        // borland
  627. SubstChar   = '_'
  628. ====================================================================
  629. Of these, two areas are of interest. The first is the "NameChars" section, which
  630. dictates which characters may be used for naming an address. For maximum flexibility
  631. (and to help make IDC scripts that automatically generate names run better), you may
  632. want to increase the characters in this section ot include the full range, i.e.
  633. "$?@"
  634. becomes:
  635. "$?@!#%^&*-+=~|\}{[]:;><,./"
  636. although this is strictly up to the user. The MangleChars section is also important for
  637. those working from code compiled with mangling set on; if the compiler of the target uses
  638. different mangling characters that the ones listed (rare), you can include them here--you
  639. can also change the character with which the mangled characters are replaced by changing
  640. the SubstChar value.
  641.  
  642.  
  643. Loading a program
  644. -----------------
  645. For all of the examples in this primer, I will be using notepad.exe as a target; I will
  646. also be assuming that the configuration changes mentioned above have been made. To begin,
  647. launch IDAW.EXE and type "c:\windows\notepad.exe" at the "Select File" dialog box, press
  648. OK.
  649.  
  650. Immediately IDA will bring up a dialog box prompting you for loading options. Make sure that
  651. Portable Executable is checked (for Win32 files), that "Create Segments", "Load Resources", and
  652. "Make Imports Section" are checked, and that "Rename DLL Entries" is unchecked. Also ensure that
  653. the "DLL directory" is set to the location of kernel32.dll et. al., usually C:\windows\system.
  654.  
  655. Press OK, and wait for the green "Ready" notice to appear in the upper left of the IDA menu bar.
  656.  
  657. A few notes about the IDA user interface may be helpful at this point. IDA uses a text-mode windowing
  658. techniques common in console-mode applications; each window has a toborder with a green square (close),
  659. a title, and a green arrow (restore/mamximize), a right border with a veritcal scroll bar, and a bottom
  660. border with a horizontal scrollbar and a green corner (resize); the windows may be moved by dragging on
  661. the title bar, or resized by dragging on the green corner. F6 switches between windows (like Alt-Tab),
  662. F7 tiles all windows (except the Messages Windows, which is like a desktop), and F8 cascades all windows.
  663.  
  664. Note that the disassembled listing is referred to as the Code Window or Text Window; you can open multiple
  665. views of the same program by selecting the View->Disassembly menu item, or by pressing F3.
  666.  
  667. As with any Windows DOS box, clicking on the small MS-DOS icon (for the system menu) gives you an Edit
  668. submenu with Mark and Copy options; to copy text out of IDA and inot a windows editor, select Edit->Mark,
  669. highlight the text you want to copy, then select Edit->Copy, then go to the windows editor and Ctrl-V
  670. (or Edit->Paste) to insert the text selected from IDA.
  671.  
  672. Viewing Imports
  673. ---------------
  674. All of the programs's imports will appear as names in the program, and may be viewed in the Names window
  675. by selecting the View->Names menu item; however as this contains all of the names in the program it may be
  676. a bit confusing. Double-clicking on the name of an inport will bring you to its entry in the .idata segment
  677. (see below).
  678.  
  679. Another way to view the imports is to select the View->Segments menu item, which will bring up the Segments
  680. window. Double-click on the .idata segment; this will jump the disassembled listing to the start of the .idata
  681. segment, which will contain all of the program's imports in pink text. To the right of each import, at the end of
  682. the line, will be a list of addresses in the program which all that import. Double-clicking on one of these
  683. addresses will jump the disassembled listing to that address.
  684.  
  685. Example: View the .idata segment of Notepad.exe as mentioned above. The imports are sorted by module; scroll down
  686. to the Kernel32.dll imports and find the one for "lstrcmpa". You should see a line like this:
  687. ª00407300 ?? ?? ?? ??       extrn lstrcmpA:dword          ; DATA XREF: sub_401FAC+15
  688. ª00407300                                                 ; sub_4045AF+3E^r
  689. ª00407300                                                 ; .text:004046B9^r
  690. ª00407300                                                 ; .text:004046DD^r
  691. Each of the locations after a ";" is an address in the file that calls lstrcmpa; these are known as cross-references,
  692. or X-refs for short. Double-click on the first one; note how it brings you to
  693. |00401FC1 FF 15 00 73 40 00 call    ds:lstrcmpA
  694. |00401FC7 85 C0             test    eax, eax
  695. |00401FC9 75 10             jnz     short loc_401FDB
  696. Press Esc to go back to the lstrcmp entry, then double-click on each of the remaining X-refs to scope out the caller
  697. code. Note how you can scout out each caller routine by double clicking on call/jmp locations within the code, and by
  698. double-clicking on X-refs to see who initiated the caller routine; Esc, as always, returns you back the way you came,
  699. one step at a time.
  700.  
  701. A final method of viewing exports is to write an IDC script. IDC is the IDA macro language; it stands for IDA-C much
  702. in the way that QCC stands for Quake-C. All IDA scripts must include the file IDC.IDC, which contains a number of
  703. internal IDA functions and constants. The IDC language is a lot like C, and is described in the file IDC.TXT--here is
  704. brief excerpt summarizing the language:
  705. ====================================================================
  706. IDC supports the following statements:
  707.   if (expression) statement
  708.   if (expression) statement else statement
  709.   for ( expr1; expr2; expr3 ) statement
  710.   while (expression) statement
  711.   do statement while (expression);
  712.   break;
  713.   continue;
  714.   return <expr>;
  715.   return;                    the same as 'return 0;'
  716.   { statements... }
  717.   expression;                     (expression-statement)
  718.   ;                         (empty statement)
  719. In expressions you may use almost all C operations except:
  720.   ++,--
  721.   complex assigment operations as '+='
  722.   , (comma operation)
  723. Here is how a function is declared :
  724.   static func(arg1,arg2,arg3) {
  725.     ...
  726.   }
  727. Here is how a variable is declared :
  728.   auto var;
  729. ====================================================================
  730. That said and done, here is a script for listing the file's exports by API module
  731. to the IDA Messages window (the blue one with all of the yellow writing on it):
  732. ====================================================================
  733. //Imports.idc : Outputs list of imported functions to the Message Window
  734. #include <idc.idc>
  735.  
  736. static GetImportSeg()
  737. {
  738.     auto ea, next, name;
  739.     ea = FirstSeg();
  740.     next = ea;
  741.     while ( (next = NextSeg(next)) != -1) {
  742.         name = SegName(next);
  743.         if ( substr( name, 0, 6 ) == ".idata" ) break;
  744.    }
  745.    return next;
  746. }
  747.  
  748. static main()
  749. {
  750.     auto BytePtr, EndImports;
  751.     BytePtr = SegStart( GetImportSeg() );
  752.     EndImports = SegEnd( BytePtr );
  753.     Message(" \n" + "Parsing Import Table...\n");
  754.     while ( BytePtr < EndImports ) {
  755.         if (LineA(BytePtr, 1) != "") Message("\n" + "____" + LineA(BytePtr,1) + "____" + "\n");
  756.         Message(Name(BytePtr) + "\n");
  757.         BytePtr = NextAddr(BytePtr);
  758.     }
  759.     Message("\n" + "Import Table Parsing Complete\n");
  760. }
  761. ====================================================================
  762. The coding is pretty straight forward if you know C: the script finds the .idata segment,
  763. prints each non-blank anterior comment line (i.e., the line that tells what API module
  764. the following imports belong to), then prints the Name of each defined/named address in the
  765. .idata section. The script is executed by pressing F2 and selecting "imports.idc", assuming
  766. that you have saved the script as imports.idc in the \IDA37?\IDC directory.
  767.  
  768. Viewing Exports
  769. ---------------
  770. Viewing exported functions s a little easier. Perhaps the quickest way is to select the Options-Name Representation
  771. menu item, and mark the "type of names" dialog so it includes only publics, as follows:
  772.  Types of names included in the list of names:
  773.    [ ] Normal
  774.    [X] Public
  775.    [ ] Autogenerated
  776.    [ ] Weak
  777. Press Ok and then select the View->Names menu item; the Names window will now only contain the exported functions of
  778. the program. As with any of the Names/Segments/etc windows, double clicking on any line will bring that function up
  779. in the "code window". [Note: if you have modified the IDA.cfg file as mentioned above, you can also browse the imports
  780. in this manner by checking only "Normal" in the dialog box illustrated above, then ignoring everything with a "str->"
  781. prefix; the remainder will be imports.]
  782.  
  783. If the program has an .edata segment, you can also view the exports there much in the same manner as in the .idata method
  784. given in the previous section. Note that Notepad has only one export ("start", the program entry point) and also has no
  785. .edata segment.
  786.  
  787. The IDC method works for exports as well. The following ID script searches for entry points into the program and displays them
  788. in the message window:
  789. ====================================================================
  790. //exports.idc : display eprogram entry points to the message window
  791. #include <idc.idc>
  792.  
  793. static main()
  794. {
  795.     auto x, ord, ea;
  796.     Message("\n Program Entry Points: \n \n");
  797.     for ( x=0; x<= GetEntryPointQty(); x = x+1){
  798.         ord =  GetEntryOrdinal( x );
  799.         ea = GetEntryPoint( ord );
  800.         Message( Name( ea ) + ":  Ordinal " + ltoa( ord,16 ) + " at offset " + ltoa( ea, 16) + "\n");
  801.     }
  802.     Message("\n" + "Export Parsing Complete\n");
  803. }
  804. ====================================================================
  805. Once again, this script may be run by pressing F2 and selecting "exports.idc".
  806.  
  807. Viewing Strings/Resources
  808. -------------------------
  809. The strings can be previewed by selecting "Normal" as the "Type of names to be shown in the list of names" in the
  810. Options->Name Representation dialog box, and then looking for everything beginning with the prefix "str->" (or "a",
  811. if using IDA straight out of the box).
  812.  
  813. In PE files, strings are commonly kept in a string table in the .rsrc segment. However, IDA does not by default
  814. parse the .rsrc segment for strings. Thus, an IDC script can be written to parse the .rsrc section for us, creating
  815. strings where any standard ASCII character is found so that the strings may be browsed either in the .rsrc segment,
  816. or in the names window:
  817. ====================================================================
  818. //RSRC_Strings.IDC
  819. //define all std ASCII characters in the .rsrc segment as strings
  820. #include <idc.idc>                //This file contains all of the
  821.                                   //function protos we will be using
  822. static main(){
  823.     auto ea;                      //auto is the standard variable type
  824.     ea = FirstSeg();              //Get Addr of first segment into ea
  825.     while (ea !=BADADDR) {
  826.         Message( "Analyzing " + SegName(ea) + "...\n" );
  827.                                   //Is this the .RSRC segment? If so...
  828.         if ( SegName(ea) == ".rsrc"){
  829.              Message("     RSRC found!\n");
  830.              while ( ea <= SegEnd(ea)) {
  831.                                  //Change every Std ASCII character into a string
  832.               if ( Byte(ea) > 0x19 && Byte(ea) < 0x7F){
  833.                 MakeStr( ea, -1 );
  834.                 MakeRptCmt(ea, Name(ea));
  835.                 ea = ea + ItemSize( ea );
  836.               }
  837.               else ea = ea + 1;
  838.             }
  839.          }
  840.         ea=NextSeg(ea);        //Goto Next Segment
  841.     }
  842.     Message("Done!\n");
  843. }
  844. ====================================================================
  845. The IDC script is functional, though not perfect (plenty of random bytes
  846. defined as strings, but it is quick up-and-running script). Notice that IDC.IDC
  847. contains a lot of function prototypes for use in IDC scripts; by including it, you
  848. are able to call all of the FirstSeg(), NextSeg(), etc functions. These functions
  849. are poorly documented, but the commented prototypes should give you enough to go
  850. on.
  851.  
  852. The IDC script can be placed in the \IDC directory and run by pressing F2 and choosing
  853. the rsrc_strings.idc script. Note that this script assumes that you have the default
  854. string type set as "Unicode"; as such it will parse any Unicode resource names or values
  855. in the .rsrc statement. For a full-fledged resource parsing IDC script a lot more work is
  856. in order; I have started such a project with a script known as reslib.idc (too large to
  857. include here) which is publicly available.
  858.  
  859. After running this script we can create and run a second one which will print out all of the
  860. strings (that is, every location name that begins with "str->") in the disassembled listing:
  861. ====================================================================
  862. //ss.idc : display all strings in the program
  863. #include <idc.idc>
  864.  
  865. static main()
  866. {
  867.     auto ea;
  868.     ea = FirstSeg();
  869.     Message("\n" + "Strings in Application: \n \n");
  870.     while( ea != BADADDR) {
  871.         if( substr( Name(ea), 0, 5) == "str->") {
  872.             Message( substr(Name(ea), 5, -1) + " at address " + ltoa( ea, 16) + "\n" );
  873.         }
  874.         ea = NextAddr(ea);
  875.     }
  876.     Message("\n" + "String Listing Complete\n");
  877. }
  878. ====================================================================
  879. Running this after the previous IDC script will reveal the flaw in
  880. the first one: a lot of garabage ASCII bytes are listed as strings--more,
  881. in fact than there are actually strings. For this reason it is important
  882. to refine your scripts so they print out only the string table and resource
  883. names in the .rsrc section (as I have done with the reslib.idc script),
  884. rather than blindly naming locations.
  885.  
  886. Searching for Strings/Code
  887. --------------------------
  888. Once you have defined strings, you can search for them using the Navigate->
  889. Search For->Text... menu item. For instance, entering the string "Cannot" at
  890. this dialog box will bring up the "YouCannotQuitWindows" string in the Code
  891. window. The shortcut for FindText is Alt-T, and for FindNextText is Ctrl-T. A
  892. "Pattern is not found" message will appear at the bottom of the message window
  893. when there are no more occurences of the text.
  894.  
  895. What if your string has not been defined? If it is not Unicode, then you can
  896. search for it using Navigate->SearchFor->Text In Core... (Alt-B), by entering
  897. the string in quotes at the dialog box, as follows:
  898. +-[_]--------------- Binary search --------------------+
  899. ▌                                                      ▌
  900. ▌ Enter search (down) string:                          ▌
  901. ▌   String "FindReplace"                            _▌▌
  902. ▌                                                      ▌
  903. ▌    [X] Case-sensitive     () Hex                    ▌
  904. ▌                           ( ) Decimal                ▌
  905. ▌                           ( ) Octal                  ▌
  906. ▌                                                      ▌
  907. ▌           OK   _    Cancel _    F1 for Help_         ▌
  908. ▌         ________    ________    ____________         ▌
  909. +------------------------------------------------------+
  910. This will find occurences of "FindReplace" in the file. You can also search
  911. for the text using the hexadecimal equivalents of the ASCII characters:
  912. +-[_]--------------- Binary search --------------------+
  913. ▌                                                      ▌
  914. ▌ Enter search (down) string:                          ▌
  915. ▌   String 46 69 6E 64                              _▌▌
  916. ▌                                                      ▌
  917. ▌    [X] Case-sensitive     () Hex                    ▌
  918. ▌                           ( ) Decimal                ▌
  919. ▌                           ( ) Octal                  ▌
  920. ▌                                                      ▌
  921. ▌           OK   _    Cancel _    F1 for Help_         ▌
  922. ▌         ________    ________    ____________         ▌
  923. +------------------------------------------------------+
  924. This will search for "Find" in the disassembled listing. In
  925. this way you can search for Unicode strings as well:
  926. +-[_]--------------- Binary search --------------------+
  927. ▌                                                      ▌
  928. ▌ Enter search (down) string:                          ▌
  929. ▌   String 43 00 61 00 6E 00 6E                     _▌▌
  930. ▌                                                      ▌
  931. ▌    [X] Case-sensitive     () Hex                    ▌
  932. ▌                           ( ) Decimal                ▌
  933. ▌                           ( ) Octal                  ▌
  934. ▌                                                      ▌
  935. ▌           OK   _    Cancel _    F1 for Help_         ▌
  936. ▌         ________    ________    ____________         ▌
  937. +------------------------------------------------------+
  938. This will search for the Unicode string "Cannot". Note that
  939. simply searching for the string "Cannot" will fail due to the
  940. 00 bytes that Unicode inserts between characters. Thus, to search
  941. effectively for Unicode strings, they must be defined first.
  942.  
  943. Searching for code can be done in the same way, using the Text In Core
  944. method. For example, the following will search for "test eax, eax":
  945. +-[_]--------------- Binary search --------------------+
  946. ▌                                                      ▌
  947. ▌ Enter search (down) string:                          ▌
  948. ▌   String 85 C0                                    _▌▌
  949. ▌                                                      ▌
  950. ▌    [X] Case-sensitive     () Hex                    ▌
  951. ▌                           ( ) Decimal                ▌
  952. ▌                           ( ) Octal                  ▌
  953. ▌                                                      ▌
  954. ▌           OK   _    Cancel _    F1 for Help_         ▌
  955. ▌         ________    ________    ____________         ▌
  956. +------------------------------------------------------+
  957. And you can use the standard Text search for opcodes as well, though
  958. you will get a lot of hits (i.e., you can search for the text "test" but not "test eax, eax";
  959. therefore you will get quite a few hits).
  960.  
  961. There is, of course, a final option to make searching for strings much easier--you must write an
  962. IDC script to front-end for the "Search for Text In Core" function. The following IDC script will
  963. do just that, allowing you to enter a text string to search for, then converting the string to
  964. hexadecimal and feeding it to the "Text In Core" function:
  965. ====================================================================
  966. // textsearch.idc : search for undefined strings
  967. #include <idc.idc>
  968.  
  969. static main()
  970. {
  971.    auto ea, x, y, searchstr, temp_c, binstr, array_id, alphabet, bin_c, cont;
  972.    ea = FirstSeg();
  973.     // ---- Create Array Of ASCII Characters ------------------------
  974.     // ---- Note that the index of each char = its decimal value ----
  975.     array_id = CreateArray("AsciiTable");
  976.     alphabet = "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz";
  977.     y = 48;
  978.     for (x = 0; x < strlen(alphabet); x = x + 1 ) {
  979.          SetArrayString( array_id, y, substr(alphabet, x, x+1));
  980.         y = y +1;
  981.     }
  982.     // ---- Prompt User For Search String ----------------------------
  983.     searchstr = AskStr("", "Enter a search string:\n");
  984.     // ---- Cycle through array looking for match --------------------
  985.     for (x = 0; x < strlen(searchstr); x = x + 1 ) {
  986.         temp_c = substr(searchstr, x, x + 1 );
  987.         for( y = GetFirstIndex(AR_STR, array_id); y <= GetLastIndex(AR_STR, array_id); y =  GetNextIndex(AR_STR, array_id, y) ) {
  988.             if (temp_c == GetArrayElement(AR_STR, array_id, y)) {
  989.                 bin_c = y;
  990.                 break;
  991.             }                                                        //End "If Match"
  992.         }                                                               //End Array Loop
  993.         binstr = form("%s %X", binstr, bin_c);       //Standard Version
  994.   //binstr = form("%s %X 00", binstr, bin_c);     //Unicode Version
  995.     }                                                                //End Search String Loop
  996.     Message("Search string is " + binstr + "\n");    //Debug Control
  997.     // -------- "Search" and "Search Again" Loop... --------------------
  998.     cont = 1;
  999.     while (cont==1) {
  1000.         ea = FindBinary(ea, 1, binstr);                    //Search From ea
  1001.         if( ea == -1) {                                        //If No Hits
  1002.             Warning("No more occurrences");                //MessageBox
  1003.             cont = 0;
  1004.             break;                                                //Leave
  1005.         }
  1006.         Jump(ea);                                            //Position Cursor At Hit
  1007.         cont = AskYN( 1, "Find next occurence?" );    //Search Again?
  1008.     }
  1009.     // --------- Cleanup and Exit
  1010.    Message("\n" + "Search Complete\n");
  1011.     DeleteArray(array_id);
  1012. }
  1013. ====================================================================
  1014.  
  1015. Location Names
  1016. --------------
  1017. In IDA, location names are your greatest asset. Naming locations whose purpose
  1018. you know or suspect allows you to quickly browse the code for references to that
  1019. location. For example, do the following:
  1020. 1. Go to the lstrcmp import listing
  1021. 2. Double Click on the first X-ref; this should put you at 00401FC1
  1022. 3. Scroll up to the start of the function (401FAC) and use the N command to name it "StringCmpFunc"
  1023. 4. Rename 401FDB to "StringCmpFailed" (because of the JNZ at 401FC9)
  1024. 5. Name 402033 to "Good String Name" (for the JMP at 401FD9)
  1025. Instantly the function is more readable. Now, go to the X-refs at 401FAC and double click on the
  1026. first one; this will put you at 00402816 (yes, we are back-tracing! Great, isn't it?). Here you are in
  1027. a great huge routine, and the "StringCmpFunc" stands out from the rest in bright yellow. The rest of the
  1028. internal functions (sub_???????) can be named in the same way.
  1029.  
  1030. Now some elementary searching browsing: You'll notice that you can see all of the names you created with
  1031. the N command in the Names window. Using Alt-T (search text), you can look for occurences of StringCmpFunc
  1032. in the disassembled listing, which will show you all of the locations that reference this function.
  1033.  
  1034. Ok, comments: you can comment code using the ";" key. Go back to the "StringCmpFailed" location (look it up
  1035. in the Names window), hit the ";" key and type in the text "Bad String Entered!". This is what is known as a
  1036. "repeatable comment". Why repeatable? Because evey address that refers to this location will now have that comment
  1037. suffixed to it--go back up to 401FC9 to verify. Cool, eh? You will never go back to W32Dasm...
  1038.  
  1039. Producing an Output File
  1040. ------------------------
  1041. Producing an output file is relatively simple. If you want a full listing of the names, comments, addresses, in
  1042. short everything in the Code Window, use File->Produce Output File->Produce LST File. If you just want the ASM
  1043. source code, with no addresses, use File->Produce Output File->Produce ASM File. If you want to produce a tiny file
  1044. that will make all of the changes that you just made to an executable (in case you want someone else to be able to
  1045. duplicate your .idb [idb: IDA database, containing all of your changes to the exe and the disassembled listing]),
  1046. use File->Produce Output File->Produce IDC file--this will create an IDc script that, when run, will leave the
  1047. disassembled listing identical to yours.
  1048.  
  1049. Advanced Technique
  1050. ------------------
  1051. 1.IDS files and Comment Databases
  1052. Custom IDS files are very useful; you will need to download the IDS utilities from
  1053. http://www.unibest.ru/~ig/idsutil.zip
  1054. Basically, you create an IDT file from a .DLL by running the DLL2IDT utility. From there you can comment the
  1055. IDT file and compress it into an IDS file using ZIPIDS, and finally move it to the appropriate subdirectory
  1056. (based on OS) of \IDS.
  1057.  
  1058. An IDT file looks like this:
  1059. ALIGNMENT 4
  1060. ;DECLARATION
  1061. ;
  1062. 0 Name=ADVAPI32.dll
  1063. ;
  1064. 1 Name=AbortSystemShutdownA
  1065. 2 Name=AbortSystemShutdownW
  1066. 3 Name=AccessCheck
  1067. 4 Name=AccessCheckAndAuditAlarmA
  1068. 5 Name=AccessCheckAndAuditAlarmW
  1069. 6 Name=AddAccessAllowedAce
  1070. 7 Name=AddAccessDeniedAce
  1071. 8 Name=AddAce
  1072. 9 Name=AddAuditAccessAce
  1073. 10 Name=AdjustTokenGroups
  1074. 11 Name=AdjustTokenPrivileges
  1075. ...
  1076.  
  1077. With this file, you can provide comments for various functions by adding "Comment=" lines to each, for example:
  1078. 154 Name=RegCreateKeyA Comment=Create a Key in the System Registry
  1079.  
  1080. Note that an IDT line has the following structure:
  1081. Ordinal Name=name Args=args Drops=drops Pascal=pascal Typeinfo=type Comment=comment RptCmt=ord#
  1082. The keywords are defined as follows:
  1083. Name     : name of entry point                            [string]
  1084. Args     : number of bytes occupied by entry point arguments  [number]
  1085. Drops    : number of bytes purged from the stack upon return  [number]
  1086. Pascal   : the same as Args=Drops= [number]
  1087. Typeinfo : entry point function prototype (type of input/output arguments [string]
  1088. Comment : a comment for this entry point [string]
  1089. Rptcmt : use the comment from the specified entry point  [number]
  1090.  
  1091. Wouldn't it be nice to have all of the API prototypes entered as comments into the IDS files? Well, it can
  1092. be done, though no-one in their right mind would attempt it by hand. One of the most basic programming tools,
  1093. grep.exe, will allow you to search an entire directory for lines in any file containing a specific search pattern.
  1094. If you were to grep an entire directory for WINAPI or STDCALL, you would then have as output a file with every
  1095. 1-line API prototype in it. The following perl script will take an .idt file and grep output file, and output an
  1096. .idt file commented with the API prototypes to stdout or a specified filename:
  1097. ====================================================================
  1098. #!/usr/bin/perl
  1099.  
  1100. if ($#ARGV == 0) {
  1101.     print "Usage: h2idt [idtfile] [grepfile] [outfile]\n";
  1102.     print "Output defaults to stdout\n";
  1103.     exit (1);
  1104. }
  1105.  
  1106. $idtfile = $ARGV[0];
  1107. $grepfile = $ARGV[1];
  1108. if ($#ARGV == 2) {
  1109.     $outfile = ">" . $ARGV[2];
  1110. } else {
  1111.     $outfile = ">-";
  1112. }
  1113. open(IDTFILE, $idtfile)|| die "Can't open file: $!\n";
  1114. open(GREPFILE, $grepfile) || die "Can't open file: $!\n";
  1115. open(OUTFILE, "$outfile") || die "Can't create file: $!\n";
  1116. $i =0;
  1117. foreach (<GREPFILE>){
  1118.     s/\n\r//;
  1119.     @greparray[$i] = $_;
  1120.     $i++;
  1121. }
  1122.  
  1123. print OUTFILE ";DECLARATION \n";
  1124. print OUTFILE ";ALIGNMENT 2 \n\n";
  1125. print OUTFILE "; Module Name and Description \n";
  1126.  
  1127. foreach (<IDTFILE>) {
  1128.     if ( /^0/ ){
  1129.         s/\\//;
  1130.         print OUTFILE $_;
  1131.         print OUTFILE ";---------------------------------------\n";
  1132.         break;
  1133.     } elsif ( /Name=/ ){
  1134.     if (/\n/){
  1135.         chop; #get rid of LF
  1136.     }
  1137.     if (/\r/){
  1138.         chop; #get rid of CR
  1139.     }
  1140.     $outstr = $_;
  1141.     ($junk, $searchstr, $junk) = split(' ', $_, 3);
  1142.     $searchstr =~ s/Name=//;
  1143.     $comment='';
  1144.     foreach(@greparray) {
  1145.         if (/\s$searchstr\(/) {
  1146.             $comment = $_;
  1147.         }
  1148.     }
  1149.     $outstr =~ s/\\//;
  1150.     if ($comment != '') {
  1151.         $comment =~ s/^[^a-zA-Z]+//;
  1152.         $comment =~ s/\n//;
  1153.         $comment =~ s/;//;
  1154.         $comment =~ s/STDCALL\s//;
  1155.         print OUTFILE $outstr, " Comment=", $comment, "\n";
  1156.     }else {
  1157.         print OUTFILE $outstr, "\n";
  1158.     }
  1159.    }
  1160. }
  1161. print OUTFILE ";------------------EOF------------------";
  1162. close(OUTFILE);
  1163. close(GREPFILE);
  1164. close(GREPTMP);
  1165. close(IDTFILE);
  1166. exit (0);
  1167. ====================================================================
  1168. As usual with Perl/unix files, strip the above for CR/LF's before you run it in perl (you can use
  1169. Editeur, or nedit for this, depending on your OS). So, how do you do this from NT? Well, assuming
  1170. you have the NT resource kit, the process for extracting and IDT file from an existing IDS file,
  1171. grepping for prototypes (I use LCC as the protos are all 1-line), creating the commented IDT file
  1172. and compressing it into an IDS file, is as follows:
  1173.  
  1174. c:\ntreskit\posix\grep STDCALL c:\lcc\include\*  > grep.out
  1175. c:\ida\Utility\IDSUtil\WIN32\zipids -u c:\ida\Ids\Win\kernel32.ids
  1176. c:\ntreskit\perl\perl.exe  h2idt kernel32.idt grep.out idt.out
  1177. c:\ida\Utility\IDSUtil\WIN32\zipids out.idt
  1178. ren out.ids kernel32.ids
  1179.  
  1180. You will get --in the IDT file-- output similar to the following:
  1181. ===========================================================================
  1182. ;DECLARATION
  1183. ;ALIGNMENT 2
  1184.  
  1185. ; Module Name and Description
  1186. 0 Name=KERNEL32.dll
  1187. ;---------------------------------------
  1188. 50 Name=AddAtomA Pascal=2 Comment=ATOM AddAtomA(LPCSTR);
  1189. 102 Name=AddAtomW Pascal=2 Comment=ATOM AddAtomW(LPCWSTR);
  1190. 103 Name=AllocConsole Pascal=0 Comment=BOOL AllocConsole(VOID);
  1191. 104 Name=AllocLSCallbac Comment=BOOL AllocConsole(VOID);
  1192. ===========================================================================
  1193. Note that eveyrthing after the "Comment=" will appear in the comment margin of IDA.
  1194.  
  1195.  
  1196. In addition to the IDS files, you can also maintain a database of comments that
  1197. will be inserted into the code upon disassembly. The IDA comment database is stored
  1198. in the IDA.INT file, and it can be modified with the LoadINT utility available at
  1199. http://www.unibest.ru/~ig/ldint37.zip
  1200.  
  1201. The Readme file best documents how to edit this database, but to show you a brief example of
  1202. the comments supplied with IDA, here is an excerpt from the PC section of the INT:
  1203. //    MMX instructions
  1204. NN_emms:    "Empty MMX state"
  1205. NN_movd:    "Move 32 bits"
  1206. NN_movq:    "Move 64 bits"
  1207. NN_packsswb:    "Pack with Signed Saturation (Word->Byte)"
  1208. NN_packssdw:    "Pack with Signed Saturation (Dword->Word)"
  1209. NN_packuswb:    "Pack with Unsigned Saturation (Word->Byte)"
  1210. NN_paddb:    "Packed Add Byte"
  1211. NN_paddw:    "Packed Add Word"
  1212. NN_paddd:    "Packed Add Dword"
  1213.  
  1214. These comments will appear (if "auto comments" is turned on) whenever the
  1215. opcode is encountered in the disassembly; note that you can browse through the .cmt files included
  1216. with LoadINT to see what the existing comments are. The most interesting will be int.cmt,  pc.cmt,
  1217. portin.cmt, portout.cmt, and vxd.cmt. It is tempting --but rather daunting-- to port Ralph Brown's
  1218. Interrupt List comments to an INT database...
  1219.  
  1220. 2.IDC Scripts
  1221. I have used IDC scripts for a number of monotonous tasks. Basically, you can use an IDC script to
  1222. parse VCL resources, to parse VB forms (if you take the time...), to encrypt or decrypt sections
  1223. of code, to print out a call trace, to perform searches for the user (e.g. a front-end to the RegEx
  1224. feature), etc.
  1225.  
  1226. Here are a quick few additional IDC scripts to demonstrate their usefulness:
  1227. ====================================================================
  1228. //copy.idc: Outputs selected text to an .asm file
  1229. //Usage: Select text with mouse or cursor, hit F2 and type copy.idc, enter a filename when prompted
  1230. //       and the selected text will be written to that file.
  1231. //Future Plans: Make this output to the Windows clipboard. I may have to patch IDA for this....
  1232. //
  1233. // code by mammon_ All rights reversed, use as you see fit.....
  1234. //------------------------------------------------------------------------------------------------------
  1235. #include <idc.idc>
  1236.  
  1237. static main(){
  1238.     auto filename, start_loc, end_loc;
  1239.     start_loc = SelStart();
  1240.     end_loc = SelEnd();
  1241.     filename = AskFile( "asm", "Output file name?");
  1242.     WriteTxt( filename, start_loc, end_loc);
  1243.     return 0;
  1244. }
  1245. ====================================================================
  1246. //------------------------------------------------------------------------------------------------------
  1247. //Haeder.idc : Imports #defines from a .h file, adds as enums
  1248. //Note:  This script prompts the user for a header file (*.h), then parses the
  1249. //       file looking for #define statements: these are then converted to members
  1250. //       of enum "Defines".
  1251. //Bugs: Only the first instance of any value will be preserved; all others will be
  1252. //      discarded with an error as you can have only one instance of any value (or
  1253. //      any name) in a single enumeration. A prompt has been added for the user to
  1254. //      name the enumerations for the header file, so that any duplicate enum values
  1255. //      can be added to a different file and enumerated under a different "enum name."
  1256. //
  1257. // code by mammon_ All rights reversed, use as you see fit.....
  1258. //------------------------------------------------------------------------------------------------------
  1259.  
  1260. #include <idc.idc>
  1261.  
  1262. static strip_spaces( BytePtr, hHeaderFile){
  1263.        auto tempc;
  1264.        fseek( hHeaderFile, BytePtr, 0);
  1265.        tempc = fgetc(hHeaderFile);
  1266.        while ( tempc == 0x20) {
  1267.         BytePtr = BytePtr + 1;
  1268.         fseek( hHeaderFile, BytePtr, 0);
  1269.         tempc = fgetc(hHeaderFile);
  1270.        }
  1271.        return BytePtr;
  1272. }
  1273.  
  1274. static FindStringEnd( StrName ){
  1275.     auto x, tempc;
  1276.     for ( x = 1; x < strlen(StrName); x = x + 1) {
  1277.         tempc = substr( StrName, x-1, x);
  1278.         if ( tempc == " ") {
  1279.             return substr( StrName, 0, x);
  1280.         }
  1281.     }
  1282.     return substr( StrName, 0, strlen(StrName));
  1283. }
  1284.  
  1285. static FixString( StrName ){
  1286.     auto x, tempc, newname;
  1287.     newname="def";    //set newname to type character
  1288.     for ( x = 1; x < strlen(StrName); x = x + 1) {
  1289.         tempc = substr( StrName, x-1, x);
  1290.         if ( tempc != "_") {
  1291.             newname = newname + tempc;
  1292.         }
  1293.     }
  1294.     return newname;
  1295. }
  1296.  
  1297. static main(){
  1298.     auto HeaderFile, hHeaderFile, fLength, BytePtr, first_str, second_str, third_str, define_val;
  1299.     auto enum_id, tempc1, x, y, errcode, define_name, FilePtr, define_str, enum_name;
  1300.     FilePtr = 0;
  1301.     Message("\nStart Conversion\n");
  1302.     HeaderFile = AskFile( "*.h", "Choose a header file to parse:");
  1303.     enum_name = AskStr("Defines", "Enter a name for the enumerations (alpha only, eg 'VMMDefines'):");
  1304.     hHeaderFile = fopen( HeaderFile, "r");
  1305.     fLength = filelength(hHeaderFile);
  1306.     if( fLength == -1) Message( "Bad File Length!\n");
  1307.     enum_id = AddEnum( GetEnumQty() + 1, enum_name, FF_0NUMH);
  1308.     if ( enum_id == -1) {
  1309.         enum_id = GetEnum( enum_name );
  1310.         if(enum_id == -1) Message("Enum #Defines not created/not found\n");
  1311.     }
  1312.     SetEnumCmt( enum_id, "#define from " + HeaderFile, 1);
  1313.     while(FilePtr < fLength ){
  1314.         FilePtr = strip_spaces( FilePtr, hHeaderFile );
  1315.         BytePtr = FilePtr;
  1316.         errcode = fseek( hHeaderFile, BytePtr, 0 );
  1317.         if ( errcode != 0) break;
  1318.         first_str = readstr( hHeaderFile );
  1319.         if ( first_str == -1 ) {
  1320.             Message( "End of file! \n" );
  1321.             break;
  1322.         }
  1323.         else if ( substr(first_str, 0, 7) == "#define" || substr( first_str, 0, 7) == "#DEFINE" ) {
  1324.             FilePtr = FilePtr + strlen( first_str );
  1325.             BytePtr = BytePtr + 7;
  1326.             BytePtr = strip_spaces( BytePtr, hHeaderFile );
  1327.             errcode = fseek( hHeaderFile, BytePtr, 0 );
  1328.             if ( errcode != 0 ) break;
  1329.             second_str = readstr( hHeaderFile );
  1330.             if ( second_str == -1 ) {
  1331.                 Message( "End of file after #define!\n" );
  1332.                 break;
  1333.             }
  1334.             else {
  1335.                 define_name = FindStringEnd( second_str );
  1336.                 define_name = FixString( define_name );
  1337.                 BytePtr = strip_spaces( BytePtr + strstr( second_str, " " ), hHeaderFile );
  1338.                 errcode = fseek( hHeaderFile, BytePtr, 0);
  1339.                 if ( errcode != 0 ) break;
  1340.                 third_str = readstr( hHeaderFile);
  1341.                 tempc1 = substr(third_str, 0, 2);
  1342.                 if ( third_str == -1) {
  1343.                     Message( "End of file before value!\n");
  1344.                     break;
  1345.                 }
  1346.                 else if ( tempc1 == "0x" || tempc1 == "0X") {
  1347.                   define_str = FindStringEnd( third_str );
  1348.                     define_val = xtol( define_str );
  1349.                     errcode = AddConst( enum_id, define_name, define_val);
  1350.                     if ( errcode == 1 ) Message( "Name " + define_name + " bad or already used in program!\n");
  1351.                     if ( errcode == 2 ) Message( "Value " + define_str + " already used in program!\n");
  1352.                     if ( errcode == 3 ) Message( "Bad enumID!\n");
  1353.                 }
  1354.             }
  1355.         }
  1356.         else FilePtr = FilePtr + strlen( first_str);
  1357.     }
  1358.     Message("\nConversion finished!\n");
  1359. }
  1360. ====================================================================
  1361. //------------------------------------------------------------------------------------------------------
  1362. //funcalls.idc : Display the calls made by a function
  1363.  
  1364. #include <idc.idc>
  1365.  
  1366. static main(){
  1367.     auto ea,x,f_end;
  1368.     ea = ChooseFunction("Select a function to parse:");
  1369.     f_end = FindFuncEnd(ea);
  1370.     Message("\n*** Code References from " + GetFunctionName(ea) + " : "  + atoa(ea) + "\n");
  1371.     for ( ea ; ea <= f_end; ea = NextAddr(ea) ) {
  1372.         x = Rfirst0(ea);
  1373.         if ( x != BADADDR) {
  1374.         Message(atoa(ea) + " refers to " + Name(x) + " : " + atoa(x) + "\n");
  1375.         x = Rnext0(ea,x);
  1376.         }
  1377.         while ( x != BADADDR) {
  1378.             Message(atoa(ea) + " refers to " + Name(x) + " : " + atoa(x) + "\n");
  1379.             x = Rnext0(ea,x);
  1380.         }
  1381.     }
  1382.     Message("End of output. \n");
  1383. }
  1384. ===================================================================
  1385. And, finally, I have referred to a reslib.idc file throughout this work. It can be found at
  1386. http://www.eccentrica.org/Mammon/Reslib.idc
  1387. with it's "caller file" at
  1388. http://www.eccentrica.org/Mammon/Res.idc
  1389.  
  1390. 3.Map files
  1391. Map files may be generated by IDA using the File->Produce Output File->Produce Map File
  1392. menu item. All of the user-created and auto-generated names (if selected) will be included
  1393. as symbols in the .MAP files, which then can be converted into Soft-Ice symbol files using
  1394. NMSYM.EXE.
  1395.  
  1396. Note that there are a few tricks to this, I recommend using Gij's MaptoMap utility for the conversion.
  1397.  
  1398. 4.ASM files
  1399. The ASM files may be used to produce compilable source code. This is not, strictly speaking, the
  1400. province of the cracker, but a bit of good practice can be found by taking various small .COM files
  1401. (such as debug, edit, or the various Crack-me's) and re-compiling them.