2

Is there any tools can auto generate enum type by macro?

For example, NTSTATUS in Windows defined as

#define STATUS_ILLEGAL_INSTRUCTION       ((NTSTATUS)0xC000001DL)   
#define STATUS_INVALID_LOCK_SEQUENCE     ((NTSTATUS)0xC000001EL)
#define STATUS_INVALID_VIEW_SIZE         ((NTSTATUS)0xC000001FL)
#define STATUS_INVALID_FILE_FOR_SECTION  ((NTSTATUS)0xC0000020L)
#define STATUS_ALREADY_COMMITTED         ((NTSTATUS)0xC0000021L)
#define STATUS_ACCESS_DENIED             ((NTSTATUS)0xC0000022L)
...

I want to import it into IDA Pro as enum, How can I do it?

1
  • Hmm, the real question is if you doing this yourself. Parsing for the status codes or something like IOCTLs in the WDK using regular expressions is fairly simple. You won't even need something that can understand more complex C statements. However, IDA may just as well have already what you want.
    – 0xC0000022L
    Jan 17, 2022 at 9:02

2 Answers 2

2

IDA may already have what you need. Otherwise parsing the WDK headers would be the way to go. I did this a very long time ago, but could not dig up the IDC files. Depending on the sample you look at, something like DriverBuddy may also come in handy.

Consider the following snippet from ntdll.dll:

call    RtlFreeHeap
test    edi, edi
jns     short loc_18001A2EA
cmp     edi, 0C0000022h
jz      short ReturnStatus
cmp     edi, 0C0000043h
jz      short ReturnStatus

Clearly 0C0000022h and 0C0000043h are NTSTATUS values. You can use the "Use standard symbolic constant" menu item from the context menu (right click on any such value):

Menu item

... and ideally you will already be presented with one or several usable choices:

"Please choose a symbol" dialog

... scrolling to the right within the dialog will also show which type lib introduced the constant(s):

Type lib used

If nothing pops up it's usually a good idea to add them yourself via File + Load file + FLIRT signature file, which should make the appropriate enums and structs available in your database:

"List of available library modules" dialog

The shown library modules would be the most appropriate for your purpose, it seems. However, if you wanted to outright add the complete enum (technically you will receive a copy of what in IDA lingo is a "standard enum"), you could do that from the enum subview (by default: Shift+F10). The subview, will be headed by a helpful reminder of the keyboard shortcuts:

; Ins/Del/Ctrl-E: create/delete/edit enumeration types
; N/Ctrl-N      : create/edit a symbolic constant
; U             : delete a symbolic constant
; ; or :        : set a comment for the current item

And so after hitting Ins you should see the following dialog:

"Add enum type" dialog

Since you have symbol names, pick option (2), if you knew the enum name you could also use (1).

"Please choose an enum" dialog

From the opening dialog we could search for STATUS_ACCESS_DENIED by typing it while the dialog is open. The search term will be helpfully shown below the list (highlighted). Once you found the constant/symbol name you were looking for, simply double click it or select it and press the OK button.

The result should show as a collapsed enum in the enum subview:

; [COLLAPSED ENUM MACRO_STATUS. PRESS CTRL-NUMPAD+ TO EXPAND]

So there you have it, had you known the name MACRO_STATUS up front, you could have added the enum by its own name instead of the name of a contained symbol.

The resulting copy of the enum can now be freely amended by you.

If you wanted to do something like this with IDC you would use something like add_enum() and add_enum_member():

id = add_enum(-1, "MACRO_STATUS", 0x1100000)
add_enum_member(id,"STATUS_ACCESS_DENIED",  0XFFFFFFFFC0000022, -1);

And if you're wondering about the odd leading 0XFFFFFFFF that's because the underlying type of NTSTATUS is LONG and therefore 32-bit signed. I was using a 64-bit IDB for this. If you use a 32-bit one you can simply get rid of the leading FFFFFFFF (but not the 0X).

After you have the enum added, you should be presented with a submenu from "Use standard symbolic constant" and inside of it you should see the appropriate symbol, which after selecting it will give us:

Context menu

call    RtlFreeHeap
test    edi, edi
jns     short loc_18001A2EA
cmp     edi, STATUS_ACCESS_DENIED
jz      short ReturnStatus
cmp     edi, STATUS_SHARING_VIOLATION
jz      short ReturnStatus
1

I don't know how proper this method is or
what dangers lurk by using these hacks but I have sometimes used the

ida -> file -> load file ->parse c header file (ctrl+f9) 

to get the job done in free versions (5 and 7)

suppose you have are analyzing a binary whose source is

#include <stdio.h>
#include <stdlib.h>
int main (int argc,char* argv[] ){
    if(argc == 2)   {
        int res = 0;
        int nts = atoi(argv[1]);
        switch (nts)        {
            case 1:
                res = 0xC000001DL;
                break;
            case 2:
                res = 0xC000001EL;
                break;
            case 3:
                res = 0xC000001FL;
                break;
            case 4:
                res = 0xC0000020L;
                break;
            case 5:
                res = 0xC0000021L;
                break;
            case 6:
                res = 0xC0000022L;
                break;
            default:
                res = 0xffffffff;
                break;              
        }
        printf("you asked %d i give %08x\n" , nts, res);
        return 0;
    }
}

whose main disassembled will look like (ida free 7)

text:000000014000106C loc_14000106C:                          ; jumptable 000000014000106A case 1
.text:000000014000106C                 mov     [rsp+38h+var_18], 0C000001Dh
.text:0000000140001074                 jmp     short loc_1400010B0
.text:0000000140001076 ; ---------------------------------------------------------------------------
.text:0000000140001076
.text:0000000140001076 loc_140001076:                          ; jumptable 000000014000106A case 2
.text:0000000140001076                 mov     [rsp+38h+var_18], 0C000001Eh
.text:000000014000107E                 jmp     short loc_1400010B0
.text:0000000140001080 ; ---------------------------------------------------------------------------
.text:0000000140001080
.text:0000000140001080 loc_140001080:                          ; jumptable 000000014000106A case 3
.text:0000000140001080                 mov     [rsp+38h+var_18], 0C000001Fh
.text:0000000140001088                 jmp     short loc_1400010B0
.text:000000014000108A ; ---------------------------------------------------------------------------
.text:000000014000108A
.text:000000014000108A loc_14000108A:                          ; jumptable 000000014000106A case 4
.text:000000014000108A                 mov     [rsp+38h+var_18], 0C0000020h
.text:0000000140001092                 jmp     short loc_1400010B0
.text:0000000140001094 ; ---------------------------------------------------------------------------
.text:0000000140001094
.text:0000000140001094 loc_140001094:                          ; jumptable 000000014000106A case 5
.text:0000000140001094                 mov     [rsp+38h+var_18], 0C0000021h
.text:000000014000109C                 jmp     short loc_1400010B0
.text:000000014000109E ; ---------------------------------------------------------------------------
.text:000000014000109E
.text:000000014000109E loc_14000109E:                          ; jumptable 000000014000106A case 6
.text:000000014000109E                 mov     [rsp+38h+var_18], 0C0000022h
.text:00000001400010A6                 jmp     short loc_1400010B0
.text:00000001400010A8 ; ---------------------------------------------------------------------------
.text:00000001400010A8
.text:00000001400010A8 def_14000106A:                          ; jumptable 000000014000106A default case
.text:00000001400010A8                 mov     [rsp+38h+var_18], 0FFFFFFFFh
.text:00000001400010B0
.text:00000001400010B0 loc_1400010B0:

you can simply make a dummy header file stuff them into an enum and use parse header after some notepad++ magic (column editing to remove #define regex substitute = etc)

:>cat tpass.h

enum  some_crap
{
STATUS_ILLEGAL_WHATSIT       =((NTSTATUS)0xC000001DL),
STATUS_INVALID_LOCKIT    =((NTSTATUS)0xC000001EL),
STATUS_INVALID_VIEWIT        = ((NTSTATUS)0xC000001FL),
STATUS_INVALID_FILEIT  =((NTSTATUS)0xC0000020L),
STATUS_ALREADY_COMMITIT        =((NTSTATUS)0xC0000021L),
STATUS_ACCESS_DENYIT  =           ((NTSTATUS)0xC0000022L)
};
:\>

use ctrl+f9 and parse it you will get compiled successfully

\ntst\tpass.h: successfully compiled
Caching 'Local Types'... ok
Caching 'Names'... ok

see gif for further details

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.