Open joelreymont opened 5 months ago
I can trick BN into doing the right thing using a couple of anonymous structures. I think BN should be able to figure it out by itself, though.
00099c68 if (PAYLOAD_NEGOTIATE_PARAM_CONFIG_LIST[sx.q(ix)].series == series && *(sx.q(ix) * 0x14 + 0x145e4c) == mount_pos_type)
00099cac int64_t ix_1 = sx.q(ix)
00099ccc struct anonymous_0
00099ccc anonymous_0.series = PAYLOAD_NEGOTIATE_PARAM_CONFIG_LIST[ix_1].series
00099ccc anonymous_0.mount_pos_type = PAYLOAD_NEGOTIATE_PARAM_CONFIG_LIST[ix_1].mount_pos_type
00099ccc struct anonymous_0_1
00099ccc anonymous_0_1.no_negotiate_flag = PAYLOAD_NEGOTIATE_PARAM_CONFIG_LIST[ix_1].no_negotiate_flag
00099ccc anonymous_0_1.sender = PAYLOAD_NEGOTIATE_PARAM_CONFIG_LIST[ix_1].sender
00099ccc anonymous_0_1.receiver = PAYLOAD_NEGOTIATE_PARAM_CONFIG_LIST[ix_1].receiver
00099ccc anonymous_0_1.foo = PAYLOAD_NEGOTIATE_PARAM_CONFIG_LIST[ix_1].field_5
00099cd0 config->series = anonymous_0.series
00099cd0 config->mount_pos_type = anonymous_0.mount_pos_type
00099cd0 config->no_negotiate_flag = anonymous_0_1.no_negotiate_flag
00099cd0 config->sender = anonymous_0_1.sender
00099cd0 config->receiver = anonymous_0_1.receiver
00099cd0 config->field5 = anonymous_0_1.foo
00099cd8 config->field6.d = PAYLOAD_NEGOTIATE_PARAM_CONFIG_LIST[ix_1].field_6
00099cdc err = 0
00099ce0 break
00099cec ix = ix + 1
Also, there's still the issue of *(sx.q(ix) * 0x14 + 0x145e4c) == mount_pos_type
not recognized as PAYLOAD_NEGOTIATE_PARAM_CONFIG_LIST[sx.q(ix)].mount_pos_type == mount_pos_type
.
Here a much better example where the problem is much worse...
struct CmdWaitItem __packed
{
uint32_t is_used;
uint32_t timeout;
uint32_t size;
uint32_t flag;
struct PacketMetaData meta;
void* payload;
void* callback;
struct SyncInfo* sync_info;
};
struct Command __packed
{
void* mutex;
__padding char _8[0x48];
__padding char _50[0x50];
__padding char _a0[0x50];
__padding char _f0[0x50];
__padding char _140[0x50];
__padding char _190[0x50];
__padding char _1e0[0x28];
void* mutex_1;
struct CmdWaitItem wait_items[0x20];
struct ChildTaskNode task;
int32_t field_a40;
__padding char _a44[4];
struct ListNode linker_list;
int16_t node_count;
__padding char _a5a[6];
struct Linker linkers[0x5];
void* mutex_2;
int16_t seqnum;
char field_d8a;
__padding char _d8b[5];
void* field_d90;
void* mem_3ff;
};
Note the super-weird structure field references into items of wait_items
, an array of struct CmdWaitItem
. Also note that there are straightforward field accesses into the same structure, e.g. cmd->wait_items[sx.q(ix)].is_used
and cmd->wait_items[sx.q(ix)].timeout
.
00063390 if (zx.d(cmd->wait_items[sx.q(ix)].is_used.b ^ 1) == 0)
000635cc ix = ix + 1
000635cc continue
00063390 else
000633c4 if (CMD_OSAL->GetTimeMs(ms: &cmd->wait_items[sx.q(ix)].timeout) != 0)
000633f0 DjiLogger_UserLogOutput(level: "linker", fmt: nullptr, "[%s:%d) get system time error", "DjiCommand_SendAsync", 0x1cb)
000633f8 err = 0xec
0006340c (&cmd->wait_items[0]:8.d)[sx.q(ix) * 0x10] = size
00063428 (&cmd->wait_items[0]:0xc.d)[sx.q(ix) * 0x10].w = flag
00063450 memcpy(&cmd->wait_items[0]:0x10.24 + (sx.q(ix) << 6), meta, 0x18)
00063470 if (meta->payload_size != 0 && meta->payload_size u<= 0x3ff)
000634a4 (&cmd->wait_items[0]:0x28.q)[sx.q(ix) * 8] = CMD_OSAL->Malloc(size: meta->payload_size)
000634c8 if ((&cmd->wait_items[0]:0x28.q)[sx.q(ix) * 8] == 0)
000634f4 DjiLogger_UserLogOutput(level: "linker", fmt: nullptr, "[%s:%d) malloc wait item data er…", "DjiCommand_SendAsync", 0x1d4)
000634f8 err_1 = 0xe2
000634fc break
00063530 memset((&cmd->wait_items[0]:0x28.q)[sx.q(ix) * 8], 0, zx.q(meta->payload_size))
00063564 memcpy((&cmd->wait_items[0]:0x28.q)[sx.q(ix) * 8], payload, zx.q(meta->payload_size))
00063580 *(cmd + ((sx.q(ix) + 9) << 6)) = callback
000635a0 *(cmd + ((sx.q(ix) + 9) << 6) + 8) = sync_info
000635b0 cmd->wait_items[sx.q(ix)].is_used.b = 1
000635e4 if (ix == 0x20)
00063610 DjiLogger_UserLogOutput(level: "linker", fmt: nullptr, "[%s:%d) not have enough resource…", "DjiCommand_SendAsync", 0x1e4)
00063618 err = 0x101
000635e4 else
00063674 for (int32_t i = 0; i s<= 0x1f; i = i + 1)
00063650 if (zx.d(cmd->wait_items[sx.q(ix)].is_used.b) != 0 && ix s<= 0x1f)
0006365c max = max + 1
Another example...
Positioning on the first 0x131960
below
00066fc8 if (*(0x131960 + sx.q(ix) * 0x14) == series && *(sx.q(ix) * 0x14 + 0x131964) == mount_pos_type)
and typing 'O' converts the code to
00066fc8 if (*(&s_coreParamConfigList + sx.q(ix) * 0x14) == series && *(sx.q(ix) * 0x14 + 0x131964) == mount_pos_type)
BN recognized the variable at the first instance of 0x131960
but not the second because it's offset. Typing
The full function
00066f48 int64_t DjiCoreParamConfig_Get(int64_t* arg1)
00066f58 enum E_DjiAircraftSeries series
00066f58 DjiAccessAdapter_GetAircraftSeries(series: &series)
00066f78 enum E_DjiAircraftSeries mount_pos_type
00066f78 DjiAccessAdapter_GetMountPositionType(mount_pos_type: &mount_pos_type)
00066f94 int32_t ix = 0
00067058 int64_t err
00067058 while (true)
00067058 if (ix u> 0xa)
00067094 DjiLogger_Output(tag: "utils", level: 0, fmt: "[%s:%d) Can't find module param …", "DjiCoreParamConfig_Get", 0xab, zx.q(series), zx.q(mount_pos_type))
00067098 err = 0x100
00067098 break
00066fc8 if (*(0x131960 + sx.q(ix) * 0x14) == series && *(sx.q(ix) * 0x14 + 0x131964) == mount_pos_type)
0006700c int64_t ix_1 = sx.q(ix)
0006702c int64_t x1_5 = *(ix_1 * 0x14 + 0x131968)
00067030 *arg1 = *(0x131960 + ix_1 * 0x14)
00067030 arg1[1] = x1_5
00067038 arg1[2].d = *(ix_1 * 0x14 + 0x131970)
0006703c err = 0
00067040 break
0006704c ix += 1
000670a0 return err
I went ahead and created a structure type
struct CoreParamConfig __packed
{
__padding char _0[0x14];
};
then set the type of s_coreParamConfigList
to struct CoreParamConfig s_coreParamConfigList[0xa]
.
The code changed some
00066fc8 if (s_coreParamConfigList[sx.q(ix)].__offset(0x0).d == series && *(sx.q(ix) * 0x14 + 0x131964) == mount_pos_type)
0006700c int64_t ix_1 = sx.q(ix)
0006702c int64_t x1_5 = *(ix_1 * 0x14 + 0x131968)
00067030 *arg1 = *(0x131960 + ix_1 * 0x14)
00067030 arg1[1] = x1_5
00067038 arg1[2].d = *(ix_1 * 0x14 + 0x131970)
0006703c err = 0
00067040 break
but pressing 'O' on that 0x131964
still didn't do a thing.
I pointed at .__offset(0x0).d
and created a field for that member.
My structure now looks like this
struct CoreParamConfig __packed
{
int32_t field_0;
};
and the code looks like this
00066fc8 if (s_coreParamConfigList[sx.q(ix)].field_0 == series && *(sx.q(ix) * 0x14 + 0x131964) == mount_pos_type)
0006700c int64_t ix_1 = sx.q(ix)
0006702c int64_t x1_5 = *(ix_1 * 0x14 + 0x131968)
00067030 *arg1 = *(0x131960 + ix_1 * 0x14)
00067030 arg1[1] = x1_5
00067038 arg1[2].d = *(ix_1 * 0x14 + 0x131970)
0006703c err = 0
00067040 break
'O' on 0x131964
doesn't do anything. 'O' on 0x131970
doesn't do anything.
'O' on 0x131960
changes the code to
00066fc8 if (s_coreParamConfigList[sx.q(ix)].field_0 == series && *(sx.q(ix) * 0x14 + 0x131964) == mount_pos_type)
0006700c int64_t ix_1 = sx.q(ix)
0006702c int64_t x1_5 = s_coreParamConfigList[ix_1].__offset(0x8)
00067030 *arg1 = s_coreParamConfigList[ix_1].field_0.q
00067030 arg1[1] = x1_5
00067038 arg1[2].d = s_coreParamConfigList[ix_1].__offset(0x10)
0006703c err = 0
00067040 break
BN lets me use 'S' on the offset to Create current member for structure multiple times giving me this bogus structure type
struct CoreParamConfig __packed
{
int32_t field_0;
char field_8[0x0];
char field_8[0x0];
char field_10[0x0];
char field_10[0x0];
};
but reanalyzing function doesn't make it use the fields.
Manually typing the structure as
struct CoreParamConfig __packed
{
int32_t field_0;
uint32_t field_1;
uint32_t field_2;
uint32_t field_3;
uint32_t field_4;
};
does fix the issue after a couple of seconds so I get the fields
00066fc8 if (s_coreParamConfigList[sx.q(ix)].field_0 == series && *(sx.q(ix) * 0x14 + 0x131964) == mount_pos_type)
0006700c int64_t ix_1 = sx.q(ix)
0006702c int64_t x1_5 = s_coreParamConfigList[ix_1].field_2.q
00067030 *arg1 = s_coreParamConfigList[ix_1].field_0.q
00067030 arg1[1] = x1_5
00067038 arg1[2].d = s_coreParamConfigList[ix_1].field_4
0006703c err = 0
00067040 break
but still no array access for *(sx.q(ix) * 0x14 + 0x131964)
.
Version and Platform (required):
Internal binary
major dine favor
.I'm getting pretty bad output from BN and it's not letting me tweak it. For example, that
0x145e4c
is the second field in the structure. And I don't understand why it's trying to grabseries1
andx1_5
as 64-bit ints instead of splitting them into separate structure field accesses.Both of series1 and x1_5 are picking up data from the same structure and should be automatically split into several field accesses instead. PAYLOAD_NEGOTIATE_PARAM_CONFIG_LIST is an array of structures that looks like this
Let me know if I should upload my database somewhere.