Vector35 / binaryninja-api

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

Changing the type of a stack-based array does not take effect the first time #5414

Open joelreymont opened 1 month ago

joelreymont commented 1 month ago

Version and Platform (required):

Internal binary major dine favor.

0006815c  struct ErrObj* DjiError_GetErrorMsgElements(int64_t err_code, struct ErrDesc* err_desc @ x8)

00068178      char* description
00068178      __builtin_memset(s: &description, c: 0, n: 0x20)

I pointed at description and set the type with 'y' to char description[0x20] this is what I got as a result

0006815c  struct ErrObj* DjiError_GetErrorMsgElements(int64_t err_code, struct ErrDesc* err_desc @ x8)
00068178      int64_t s
00068178      __builtin_memset(s: &s, c: 0, n: 0x20)

Typing s and changing it to char description[0x20] does the right thing

0006815c  struct ErrObj* DjiError_GetErrorMsgElements(int64_t err_code, struct ErrDesc* err_desc @ x8)
00068178      char description[0x20]
00068178      __builtin_memset(s: &description, c: 0, n: 0x20)

but why not the first time around?

I was able to reproduce this several times by undoing my changes.

negasora commented 1 month ago

Here's a binary that repros the issue: a.txt

  1. Go to main
  2. Change var_38 to char str[0x20]
  3. Change str to char* str2
  4. Notice that the user-defined name gets undefined ~and it's marked low-confidence~

Edit: Ok it's not marked low confidence, it's grayed out because it's dead code

joelreymont commented 1 month ago

Here's the main I see

00001139  int32_t main(int32_t argc, char** argv, char** envp)

00001141      int32_t argc_1 = argc
00001144      char** argv_1 = argv
00001148      char** envp_1 = envp
0000114c      void* fsbase
0000114c      int64_t rax = *(fsbase + 0x28)
0000115b      int64_t s
0000115b      __builtin_memset(s: &s, c: 0, n: 0x20)
00001184      *(fsbase + 0x28)
0000118d      if (rax == *(fsbase + 0x28))
00001195          return 0
0000118f      __stack_chk_fail()
0000118f      noreturn

Looked at the stack view to figure out that var_38 must be s.

Changed the type of s to char str[0x20] and got

00001139  int32_t main(int32_t argc, char** argv, char** envp)

00001141      int32_t argc_1 = argc
00001144      char** argv_1 = argv
00001148      char** envp_1 = envp
0000114c      void* fsbase
0000114c      int64_t rax = *(fsbase + 0x28)
0000115b      char str[0x20]
0000115b      __builtin_memset(s: &str, c: 0, n: 0x20)
00001184      *(fsbase + 0x28)
0000118d      if (rax == *(fsbase + 0x28))
00001195          return 0
0000118f      __stack_chk_fail()
0000118f      noreturn

Everything worked as expected.

negasora commented 1 month ago

Change it to char* str after

joelreymont commented 1 month ago

Yes, it went back to s and the type was greyed-out so must be low confidence.

My original complaint was that the process was going the other way around, though, and I had to ask BN to make my type twice. Did it decide it was a low-confidence type the first time around?

negasora commented 1 month ago

That's my current guess

joelreymont commented 1 month ago

I don't know if BN is working as intended here so feel free to close the issue.

I object to BN claiming that I'm wrong, though, given that I'm right in the end 🤷🏼‍♂️.

negasora commented 1 month ago

Definitely not working as intended :P