这只是垃圾吗?

逆向工程 反编译
2021-07-07 10:16:59

我有一些使用 Hex Rays 的反编译代码。我可以看到有一个内存复制操作,但我迷失在代码之后尝试使用诸如_floatsidf. 这段代码试图做什么?

int __fastcall v6495(const void *a1, size_t a2)
{
  const void *v2; // r6@1
  size_t v3; // r7@1
  int v4; // r0@1
  int v5; // r7@1
  __int64 v6; // r8@1
  int v7; // r1@1
  int v8; // r0@1
  __int64 v9; // r0@1
  __int64 v10; // r0@1
  __int64 v11; // ST00_8@1
  int v12; // r1@1
  int v13; // r0@1
  __int64 v14; // r0@1
  int v15; // r0@1
  int v16; // r1@1
  __int64 v17; // r0@1

  v2 = a1;
  v3 = a2;
  gettimeofday(&v824, 0);
  pthread_mutex_lock((pthread_mutex_t *)(v217 + 110720));
  v4 = v217;
  *(_DWORD *)(v217 + 73728) = -2028273664;
  memcpy((void *)(v4 + 73732), v2, v3);
  pthread_cond_signal((pthread_cond_t *)(v217 + 110976));
  pthread_cond_wait((pthread_cond_t *)(v217 + 111232), (pthread_mutex_t *)(v217 + 110720));
  pthread_mutex_unlock((pthread_mutex_t *)(v217 + 110720));
  v5 = v217;
  gettimeofday(&v825, 0);
  LODWORD(v6) = _floatsidf(v825.tv_sec);
  HIDWORD(v6) = v7;
  v8 = _floatsidf(v825.tv_usec);
  LODWORD(v9) = _divdf3(v8);
  LODWORD(v10) = _aeabi_dadd(v6, v9);
  v11 = v10;
  LODWORD(v6) = _floatsidf(v824.tv_sec);
  HIDWORD(v6) = v12;
  v13 = _floatsidf(v824.tv_usec);
  LODWORD(v14) = _divdf3(v13);
  v15 = _aeabi_dadd(v6, v14);
  LODWORD(v17) = _subdf3(v11, HIDWORD(v11), v15, v16);
  unk_408D81C8 = v17;
  return v5 + 73732;
}

blabb的回答之后

v217v6520.bss中的前一个函数中初始化

int v3480()
{
  __int32 v0; // r0@1

  v0 = time(0);
  srand48(v0);
  v877 = &v3688;
  v1277 = &v7299;
  v1634 = &v5690;
  v2042 = &v7024;
  v873 = &v3688;
  v872 = &unk_40ABAFB5;
  v1274 = &v7299;
  v485 = &unk_40ABAFF5;
  v1631 = &v5690;
  v1629 = &unk_40ABAFD9;
  v2037 = &v7024;
  v2038 = &unk_40ABAFE9;
  v5661 = -1;
  v2325 = -1;
  v1259 = -1;
  v4048 = -1;
  v5509 = &v5497;
  v3845 = &unk_40ABAEEC;
  v3522 = &v4191;
  v7253 = &unk_40ABAEE4;
  v2081 = &v3009;
  v5828 = &unk_40ABAEDC;
  v7014 = &v2061;
  v3636 = &unk_40ABAED4;
  v221 = &v6523;
  v218 = &v6524;
  v219 = &v6525;
  v217 = &v6520;
  v1455 = &v6523;
  unk_40ABAEF4 = &v6524;
  v7297 = &dword_409581D0;
  v5530 = &dword_409581D0;
  if ( dword_409581D0 )
  {
    v6935();
  }
  else
  {
    v4335();
    dword_409581D0 = 1;
  }
  return 0;
}
3个回答

这只是垃圾吗?不。

_floatsidf 有什么作用?它在软件浮点实现中将整数转换为双精度数。

首先,Hex-Rays 反编译器生成类似 C 的伪代码。你看的不是代码。在某些情况下,像这样,通过阅读程序集来反转它会更容易。你看到的很多都是垃圾,因为有反编译器引入的反编译人工制品。我建议您首先了解程序集的工作原理,然后学习如何以交互方式使用反编译器来修复人工制品。

反编译器工件

不正确的返回类型

LODWORD(v6) = _floatsidf(v825.tv_sec);
HIDWORD(v6) = v7;

变量v7未初始化。查看声明,我们可以看到它的值来自r1

int v7; // r1@1

因为该_floatsidf函数返回一个double跨越r0分割r1,并且 Hex-Rays 不知道这一点,所以它不能正确地表示这一点。这两行最好写成:

v6 = _floatsidf(v825.tv_sec);

不正确的参数类型

让我们跳过一点:

LODWORD(v9) = _divdf3(v8);

快速网络搜索显示进行_divdf3浮点除法,并采用两个参数。Hex-Rays 丢弃了第二个参数,所以你无法知道它是什么。

_subdf3 还需要两个参数,而不是四个,这是另一个反编译器人工制品(两个 64 位参数已拆分为四个 32 位参数)。

最后,搜索_aeabi_dadd显示它是adddf3执行加法的别名

这段代码试图做什么?

// v217 relative globals
int dword_12000;
char buf_12004[???];
pthread_mutex_t mutex_1b080;
pthread_cond_t cond_1b180;
pthread_cond_t cond_1b280;

int __fastcall v6495(const void *data, size_t length) {

    gettimeofday(&g_start_time, 0);

    pthread_mutex_lock(&mutex_1b080);
    dword_12000 = 0x871b0000;
    memcpy(buf_12004, data, length);
    pthread_cond_signal(&cond_1b180);
    pthread_cond_wait(&cond_1b280, &mutex_1b080);
    pthread_mutex_unlock(&mutex_1b080);

    gettimeofday(&g_end_time, 0);

    double v11 = (double)(g_end_time.tv_sec) + (double)(g_end_time.tv_usec) / ???;
    double v15 = (double)(g_start_time.tv_sec) + (double)(g_start_time.tv_usec) / ???;
    unk_408D81C8 = v11 - v15;

    return buf_12004;
}

问号在反编译过程中已经被破坏了,但是从上下文推断,它们可能是1000000.0,并且unk_408D81C8可能是经过的时间(以秒为单位)。

请不要问这样的问题。诸如“这段代码试图做什么?”之类的问题 或“这是垃圾吗?” 对这个社区贡献很少,感觉有点像 Stack Overflow 上的“请做我的功课”问题。一个更有用的问题可能是“如何使用 Hex-Rays 反转 ARM 软浮动?”

http://opensource.apple.com/source/clang/clang-503.0.38/src/projects/compiler-rt/lib/floatsidf.c

//===-- lib/floatsidf.c - integer -> double-precision conversion --*- C -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements integer to double-precision conversion for the
// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even
// mode.
//
//===----------------------------------------------------------------------===//

#define DOUBLE_PRECISION
#include "fp_lib.h"

#include "int_lib.h"

ARM_EABI_FNALIAS(i2d, floatsidf)

fp_t __floatsidf(int a) {

    const int aWidth = sizeof a * CHAR_BIT;

    // Handle zero as a special case to protect clz
    if (a == 0)
        return fromRep(0);

    // All other cases begin by extracting the sign and absolute value of a
    rep_t sign = 0;
    if (a < 0) {
        sign = signBit;
        a = -a;
    }

    // Exponent of (fp_t)a is the width of abs(a).
    const int exponent = (aWidth - 1) - __builtin_clz(a);
    rep_t result;

    // Shift a into the significand field and clear the implicit bit.  Extra
    // cast to unsigned int is necessary to get the correct behavior for
    // the input INT_MIN.
    const int shift = significandBits - exponent;
    result = (rep_t)(unsigned int)a << shift ^ implicitBit;

    // Insert the exponent
    result += (rep_t)(exponent + exponentBias) << significandBits;
    // Insert the sign bit and return
    return fromRep(result | sign);
}

您可能需要找到v217 初始化的位置

乍一看,它似乎是垃圾,因为所有功能似乎都在返回。

v5 + const其中v5 = v217似乎没有被初始化。

顺便说一句,Google first hit 返回_floatsidfLLVMintodpfloat()函数的源代码