Add Outlining Support for strcat

Open
#5,489 13 comments 3 reactions 1 assignee View on GitHub

@bpotchik is already working on this.

Since Jun 23, 2025.

Assessment

This issue has not been assessed yet.

Description

Component: Core Effort: Medium Impact: Low

What is the feature you'd like to have?

Currently, in the binary I am looking at, there are a number of string operations that are treated as raw hex numbers applied to variable offsets. It would be nice if these showed in a more 'as it would appear in the code' way, of just general string operations.

Is your feature request related to a problem?

There are other similar examples in the binary (macOS, x86_64) I'm looking at, but this is the most self contained one:

  005851a0  int64_t SerumGUI::getPath_AppDataBase(int64_t arg1, int64_t* arg2)
  005851b5      int64_t rax = *___stack_chk_guard
  005851d4      void var_70
  005851d4      if (_FSFindFolder(0xffff8005, 0x61737570, 0, &var_70) == 0)
  005851dc          int64_t rax_2 = _CFURLCreateFromFSRef(0, &var_70)
  005851f1          _CFURLGetFileSystemRepresentation(rax_2, 0, arg2, 0x200)
  005851f9          _CFRelease(rax_2)
  00585201          int64_t rax_3 = _strlen(arg2)
🐛00585210          *(arg2 + rax_3) = 0x6566782e6d6f632f
🐛0058521e          *(arg2 + rax_3 + 8) = 0x7364726f63657272
🐛0058522d          *(arg2 + rax_3 + 0x10) = 0x2f6d757265732e
  00585239      int64_t rax_4 = *___stack_chk_guard
  00585240      if (rax_4 != rax)
  0058524b          ___stack_chk_fail()
  0058524b          noreturn
  0058524a      return rax_4

If I right click -> Display As -> Character Constant on those hex constants, it looks a bit more readable:

    005851a0  int64_t SerumGUI::getPath_AppDataBase(int64_t arg1, int64_t* arg2)
    005851b5      int64_t rax = *___stack_chk_guard
    005851d4      void var_70
    005851d4      if (_FSFindFolder(0xffff8005, 0x61737570, 0, &var_70) == 0)
    005851dc          int64_t rax_2 = _CFURLCreateFromFSRef(0, &var_70)
    005851f1          _CFURLGetFileSystemRepresentation(rax_2, 0, arg2, 0x200)
    005851f9          _CFRelease(rax_2)
    00585201          int64_t rax_3 = _strlen(arg2)
- 🐛00585210          *(arg2 + rax_3) = 0x6566782e6d6f632f
- 🐛0058521e          *(arg2 + rax_3 + 8) = 0x7364726f63657272
- 🐛0058522d          *(arg2 + rax_3 + 0x10) = 0x2f6d757265732e
+ 🐛00585210          *(arg2 + rax_3) = '/com.xfe'
+ 🐛0058521e          *(arg2 + rax_3 + 8) = 'rrecords'
+ 🐛0058522d          *(arg2 + rax_3 + 0x10) = '.serum/'
    00585239      int64_t rax_4 = *___stack_chk_guard
    00585240      if (rax_4 != rax)
    0058524b          ___stack_chk_fail()
    0058524b          noreturn
    0058524a      return rax_4

But it would be nicer if it was automatically something more like this (or similar):

    005851a0  int64_t SerumGUI::getPath_AppDataBase(int64_t arg1, int64_t* arg2)
    005851b5      int64_t rax = *___stack_chk_guard
    005851d4      void var_70
    005851d4      if (_FSFindFolder(0xffff8005, 0x61737570, 0, &var_70) == 0)
    005851dc          int64_t rax_2 = _CFURLCreateFromFSRef(0, &var_70)
    005851f1          _CFURLGetFileSystemRepresentation(rax_2, 0, arg2, 0x200)
    005851f9          _CFRelease(rax_2)
    00585201          int64_t rax_3 = _strlen(arg2)
- 🐛00585210          *(arg2 + rax_3) = 0x6566782e6d6f632f
- 🐛0058521e          *(arg2 + rax_3 + 8) = 0x7364726f63657272
- 🐛0058522d          *(arg2 + rax_3 + 0x10) = 0x2f6d757265732e
+ 🐛00585210          *(arg2 + rax_3) = '/com.xferrecords.serum/'
    00585239      int64_t rax_4 = *___stack_chk_guard
    00585240      if (rax_4 != rax)
    0058524b          ___stack_chk_fail()
    0058524b          noreturn
    0058524a      return rax_4

Or even better would be:

    005851a0  int64_t SerumGUI::getPath_AppDataBase(int64_t arg1, int64_t* arg2)
    005851b5      int64_t rax = *___stack_chk_guard
    005851d4      void var_70
    005851d4      if (_FSFindFolder(0xffff8005, 0x61737570, 0, &var_70) == 0)
    005851dc          int64_t rax_2 = _CFURLCreateFromFSRef(0, &var_70)
    005851f1          _CFURLGetFileSystemRepresentation(rax_2, 0, arg2, 0x200)
    005851f9          _CFRelease(rax_2)
-   00585201          int64_t rax_3 = _strlen(arg2)
- 🐛00585210          *(arg2 + rax_3) = 0x6566782e6d6f632f
- 🐛0058521e          *(arg2 + rax_3 + 8) = 0x7364726f63657272
- 🐛0058522d          *(arg2 + rax_3 + 0x10) = 0x2f6d757265732e
+ 🐛00585210          _strcat(arg2, "/com.xferrecords.serum/")
    00585239      int64_t rax_4 = *___stack_chk_guard
    00585240      if (rax_4 != rax)
    0058524b          ___stack_chk_fail()
    0058524b          noreturn
    0058524a      return rax_4

Are any alternative solutions acceptable?

Unsure.

Additional Information:

image

image

image

image

image

  • This last screenshot shows another thing that would be nice to improve (which maybe is worth opening as a separate issue), where 32 bit shifts are also being used within the string operations
Dominant language
C++
Stars
1.3k
Forks
298
Avg merge
5d 5h
Merged PRs (30d)
19

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Vector35/binaryninja-api

All issues in Vector35/binaryninja-api

Similar issues

More C++ issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.