Vector35 / binaryninja-api

Public API, examples, documentation and issues for Binary Ninja
https://binary.ninja/
MIT License
948 stars 213 forks source link

Ability to found `or`ed constants even if no enumeration type is set #4912

Open op2786 opened 10 months ago

op2786 commented 10 months ago

I'm not sure if this is a bug or missing feature. In the example below 0xf0 actually means PAGE_EXECUTE_WRITECOPY|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_READ|PAGE_EXECUTE but I cannot set that value to enumeration. It would be very useful if BN can do that when I try to set enumeration with M shortcut.

int64_t query_mem_info(int64_t addr)

MEMORY_BASIC_INFORMATION lpBuffer
VirtualQuery(addr, &lpBuffer, 0x30)

if (lpBuffer.State == MEM_COMMIT && (lpBuffer.Protect.b & 0xf0) != 0) {
  return 1
}

return 0

Actually I found other examples where BN automatically did that. For example:

uint32_t uMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX)

SetErrorMode have a type like this: uint32_t SetErrorMode(enum THREAD_ERROR_MODE uMode). So I assume BN do this automatically if enumeration type is set. I tried to change the type of Protect from DWORD to PAGE_PROTECTION_FLAGS but it didn't work. Also I don't think that this should be the solution for this issue, instead, BN should be able to do it even if there is no enumeration type is set.

xusheng6 commented 10 months ago

@op2786 do you have a binary to reproduce this?

plafosse commented 10 months ago

I think the problem here is that the enumeration we have defined is not an un-ambiguous bit field enumeration

For instance: PAGE_ENCLAVE_SS_FIRST == PAGE_ENCLAVE_DECOMMIT | PAGE_NOACCESS and PAGE_ENCLAVE_MASK == PAGE_ENCLAVE_DECOMMIT

Currently we don't have any way to disambiguate enumeration masks. Or provide multiple different ways to view an enumeration's component parts. I bet if you remove SEC_IMAGE_NO_EXECUTE and PAGE_ENCLAVE_* then it would work as you expect.

So I see one of 3 possibilities here:

  1. We provide a number of possible representations the user can chose from (I think this is my preferred way)
  2. We add some additional information to the enumeration to specificially mark "mask" type enumeration values.
  3. We add an explicit __bitfield_enum designator that is then able to automatically idendify "masks" and warn when the bitfield is ambiguous.
plafosse commented 10 months ago

Hmm I guess there is one other way of doing this 🤔 ... perhaps we don't need to guarantee the whole enumeration is a bitfield but instead we can just ensure that they constants in use are unambiguous.... this could actually be pretty easy to do.

xusheng6 commented 8 months ago

v35 folks should search springbuck suffusive rustles neoplastic benzine to find the binary