簡體   English   中英

如何從C源和asm輸出反向設計結構細節?

[英]How to reverse engineer struct details from C source and asm output?

我試圖理解這個問題的解決方案

鑒於下面的C代碼和編譯器的asm輸出, AB什么?

答案: A是5, B是6。

我猜測必須進行某種划分,因為96和48都可以被6整除,20可以被5整除。

編輯: 我在網上找到了答案。 但是我不確定它是否准確
“一個字母從任何一個BYTE開始

短路僅在偶數字節處開始

一個int從BYTE開始,但可被4整除

很快就開始了BYTE,可以被8整除

str1.w很長,從5到8開始

str1.x可能有184或180

str2.p是int從值8開始,因此str1.array保持5到8個BYTES

str2.q短期可能是14到20

str2.z可能是32

char w [A] [B]和int X.

8 184

STR2。

short [B] int p doublez [B] short q

20 4 8 9

因此A = 5和B = 6“的值

代碼如下:

// #define A  ??   // 5
// #define B  ??   // 6, but the question is how to figure that out from the asm
typedef struct {
    char w[A][B];
    int x;
} str1;

typedef struct {
    short y[B];
    int p;
    double z[B];
    short q; 
} str2;

void doSub(str1 *t, str2 *u) {
    int v1 = u->p;
    int v2 = u->q;
    t->x = v1-v2;
}

為doSub過程生成的匯編代碼:

# t in %rdi, u in %rsi
doSub:
    movswl   96(%rsi), %edx
    movl     20(%rsi), %eax
    subl     %edx, %eax
    movl     %eax, 48(%rdi)
    ret

匯編代碼告訴您C代碼中使用的字段的偏移量。 所以,你可以說

offsetof(str1, x) == 48
offsetof(str2, p) == 20
offsetof(str2, q) == 96

現在讓我們來看看p 它來自ysizeof(short)可能是2(除非這是一個非常不尋常的機器或編譯器),所以這告訴我們B*2 + padding == 20 所以B最多為10,可能不是8或更少。

qsizeof(double)可能是8(再次,除非異常),所以20 + sizeof(int) + 8*B + padding == 96 如果sizeof(int) == 4 (常見,雖然int的不同大小比short / double更常見),這給了我們8*B + padding == 72 所以B最多為9.因為short可能比double更少限制,所以可能沒有填充,給出B==9 ,與p之前的2個字節填充一致

看看strsizeof(char) == 1 (總是),所以A*9 + padding = 48 所以A的最可能值是5,有3個字節的填充。

當然,編譯器可以自由添加它想要的任何填充,因此AB任何較小值都是可能的,盡管是浪費。

asm顯然適用於AMD64 SysV ABI標簽wiki中的更多鏈接)。 我的結論是,它是x86-64代碼,前兩個參數是%rdi%rsi 您找到的答案中給出的對齊規則與ABI的結構布局規則相匹配:這些類型具有自然對齊方式。 (n字節類型是n字節對齊的,除了10B long double(x87格式),它是16B對齊的)。


您找到的答案與您的C和asm不匹配 ,因此A和B值不同。 對不起,我在整理問題時沒有檢查這個,我只是假設,因為用編譯器檢查答案是微不足道的。

您找到的SO答案確實具有不同的結構和不同的asm輸出,因此數值解決方案中的任何相似性只是巧合。 很好的工作@MichaelPetch找到原始來源(並將格式化的標記復制到問題中)。


以下代碼使用godbolt編譯器資源管理器上的gcc 5.3 -O3生成與實際問題完全相同的asm:

#define A  5
#define B  9
typedef struct {
    char w[A][B];      // stored from 0 to A*B - 1
    int x;             // offset = 48 = A*B padded to a 4B boundary
} str1;

typedef struct {
    short y[B];        // 2*B bytes
    int p;             // offset = 20 = 2*B rounded up to a 4byte boundary
    double z[B];       // starts at 24 (20+4, already 8byte aligned), ends at 24 + 8*B - 1
    short q;           // offset = 96 = 24 + 8 * B
} str2;

void doSub(str1 *t, str2 *u) {
    int v1 = u->p;
    int v2 = u->q;
    t->x = v1-v2;
}

我在asm中添加了我們對結構的評論。

  • str2只依賴於B,並且沒有歧義,所以我們可以在擔心A之前解決B

    96 = 24 + 8 * B
    72 = 8 * B
    72/8 = 9 = B

  • 一旦我們有了Bstr1給了我們A

    48 = align4(A*B) = align4(A*9)
    45 <= A*9 <= 48
    5 <= A <= 5.333
    只有一個整數解: A == 5

雖然老實說,通過反復試驗解決問題的速度更快,因為編譯器資源管理器網站會在任何更改后自動重新編譯。 很容易迭代到B的正確值,以產生96和20個偏移。

你的A已經是正確的了,但由於這個問題是可以分離的,所以很容易就可以了。 在2個未知情形中,從未有過2個聯立方程。


這就是“解決方案”開始偏離軌道的地方。 您確定它是您發布的完全相同問題的解決方案嗎?

str1.w很長,從5到8開始
str1.x可能有184或180

你發布的代碼中的str1.w是一個二維char數組,從結構的開頭開始。

str1.x從48字節開始進入str1 ,正如我們從asm中看到的那樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM