qilingframework / qiling

A True Instrumentable Binary Emulation Framework
https://qiling.io
GNU General Public License v2.0
5.14k stars 744 forks source link

memonic pcmpistri return incorrect index #1374

Closed Namtv2312 closed 1 year ago

Namtv2312 commented 1 year ago

*Describe the bug memonic pcmpistri COMMAND return incorrect index , when I emul samples x86 intel, that using little-edian, but pcmpistri compare big-edian, so result is 16 ...

Sample Code

Expected behavior Correct index is ECX = 1,

Screenshots image1 image

Additional context what I need do?

elicn commented 1 year ago

That might be a Unicorn bug, but it lacks some data. What are the values of xmm0 and *(eax - 0x10) ? Can you isolate the case to a specific shellcode we can use to reproduce the scenario?

Namtv2312 commented 1 year ago

This thing is in project https://github.com/stephenfewer/ReflectiveDLLInjection/tree/master When build and run, go to VA= 0040172F , or Fileoffset= B2F, have code: image , with value: xmm0 = 0x726564616F4C6576697463656C666552, *(eax - 0x10) = b'_ReflectiveLoader@4' like picture above ( in Qiling is also true this value), but as I understand it seems that Command pcmpistri, searched is in big-edian order, so it doesn't find it, and sets ECX = 0x10, and that is wrong, .. do you need any more ?

Namtv2312 commented 1 year ago

This thing is in project https://github.com/stephenfewer/ReflectiveDLLInjection/tree/master When build and run, go to VA= 0040172F , or Fileoffset= B2F, have code: image , with value: xmm0 = 0x726564616F4C6576697463656C666552, *(eax - 0x10) = b'_ReflectiveLoader@4' like picture above ( in Qiling is also true this value), but as I understand it seems that Command pcmpistri, searched is in big-edian order, so it doesn't find it, and sets ECX = 0x10, and that is wrong, .. do you need any more ?

Namtv2312 commented 1 year ago

That might be a Unicorn bug, but it lacks some data. What are the values of xmm0 and *(eax - 0x10) ? Can you isolate the case to a specific shellcode we can use to reproduce the scenario?

Can you help anymore?

elicn commented 1 year ago

We need the numeric value of *(eax - 0x10), so we have all 3 values of that instruction.

Namtv2312 commented 1 year ago

We need the numeric value of *(eax - 0x10), so we have all 3 values of that instruction.

here: dear Sir: *(eax - 0x10) = 5f5265666c6563746976654c6f616465724034

elicn commented 1 year ago

That value is longer than 128 bits, so I truncated it to 0x666c6563746976654c6f616465724034 It appears that 16 is actually the correct result, see here.

Namtv2312 commented 1 year ago

That value is longer than 128 bits, so I truncated it to 0x666c6563746976654c6f616465724034 It appears that 16 is actually the correct result, see here.

Are you wrong: why not: xmmword ptr ds:[eax-10] = 5f5265666c6563746976654c6f616465 then, pcmpistri xmm0, xmmword ptr ds:[eax-10], C Result: ECX = 1. Same picture in X32DBG, below image After: image

elicn commented 1 year ago

According to the screenshots you added the value is actually 0x6564616f4c6576697463656c6665525f (little-endian representation of the string). I adjusted the code and you are right: the result should be 1, see here.

I compiled the same code locally and emulated it in Qiling, and the result is indeed wrong: image

This is a Unicorn bug.

Test code for future reference:

/**
 * compile: gcc -Wall -m64 -O1 -msse4.2 xmm-test.c -o xmm-test
 */

#include <stdio.h>

#include <emmintrin.h>
#include <nmmintrin.h>

int main(void)
{
    const char xmm0_data[] = "ReflectiveLoader";    // 0x726564616F4C6576697463656C666552
    const char xmm1_data[] = "_ReflectiveLoader@4"; // 0x6564616f4c6576697463656c6665525f

    const __m128i xmm0 = _mm_loadu_si128((const __m128i* const) xmm0_data);
    const __m128i xmm1 = _mm_loadu_si128((const __m128i* const) xmm1_data);

    const int res = _mm_cmpistri(xmm0, xmm1, _SIDD_CMP_EQUAL_ORDERED);

    printf("%d\n", res);

    return 0;
}
Namtv2312 commented 1 year ago

According to the screenshots you added the value is actually 0x6564616f4c6576697463656c6665525f (little-endian representation of the string). I adjusted the code and you are right: the result should be 1, see here.

I compiled the same code locally and emulated it in Qiling, and the result is indeed wrong: image

This is a Unicorn bug.

Test code for future reference:

/**
 * compile: gcc -Wall -m64 -O1 -msse4.2 xmm-test.c -o xmm-test
 */

#include <stdio.h>

#include <emmintrin.h>
#include <nmmintrin.h>

int main(void)
{
    const char xmm0_data[] = "ReflectiveLoader";    // 0x726564616F4C6576697463656C666552
    const char xmm1_data[] = "_ReflectiveLoader@4"; // 0x6564616f4c6576697463656c6665525f

    const __m128i xmm0 = _mm_loadu_si128((const __m128i* const) xmm0_data);
    const __m128i xmm1 = _mm_loadu_si128((const __m128i* const) xmm1_data);

    const int res = _mm_cmpistri(xmm0, xmm1, _SIDD_CMP_EQUAL_ORDERED);

    printf("%d\n", res);

    return 0;
}

So, what's next to do?, any help? 😀Thanks.

elicn commented 1 year ago

Go ahead and open an issue in Unicorn. You may either link to this issue, or use the repo above.