printf 如何损坏字符串?

发布于 2024-10-21 04:54:33 字数 3927 浏览 2 评论 0原文

我正在尝试对一个没有源代码的函数进行逆向工程,并且该函数受到反调试器的保护。

不管怎样,我感兴趣的是调用者程序集中的函数 PyRun_ConsoleString 是:

CPU Disasm
Address   Hex dump          Command                                                             Comments
200DAB20  /$  68 D8961A20   PUSH OFFSET 201A96D8                                                ; ASCII "__main__"
200DAB25  |.  FF15 B0331720 CALL DWORD PTR DS:[<&vampire_python21.PyImport_AddModule>]
200DAB2B  |.  83C4 04       ADD ESP,4
200DAB2E  |.  85C0          TEST EAX,EAX
200DAB30  |.  74 4C         JE SHORT 200DAB7E
200DAB32  |.  50            PUSH EAX
200DAB33  |.  FF15 8C331720 CALL DWORD PTR DS:[<&vampire_python21.PyModule_GetDict>]
200DAB39  |.  50            PUSH EAX
200DAB3A  |.  50            PUSH EAX
200DAB3B  |.  8B4424 10     MOV EAX,DWORD PTR SS:[ESP+10]
200DAB3F  |.  68 00010000   PUSH 100
200DAB44  |.  50            PUSH EAX
200DAB45  |.  FF15 90331720 CALL DWORD PTR DS:[<&vampire_python21.PyRun_ConsoleString>]
200DAB4B  |.  83C4 14       ADD ESP,14
200DAB4E  |.  85C0          TEST EAX,EAX
200DAB50  |.  75 08         JNE SHORT 200DAB5A
200DAB52  |.  FF15 94331720 CALL DWORD PTR DS:[<&vampire_python21.PyErr_Print>]
200DAB58  |.- EB 1E         JMP SHORT <JMP.&vampire_python21.Py_FlushConsoleOutput>             ; Jump to vampire_python21.Py_FlushConsoleOutput
200DAB5A  |>  FF08          DEC DWORD PTR DS:[EAX]
200DAB5C  |.  75 0A         JNE SHORT 200DAB68
200DAB5E  |.  8B48 04       MOV ECX,DWORD PTR DS:[EAX+4]
200DAB61  |.  50            PUSH EAX
200DAB62  |.  FF51 18       CALL DWORD PTR DS:[ECX+18]
200DAB65  |.  83C4 04       ADD ESP,4
200DAB68  |>  FF15 98331720 CALL DWORD PTR DS:[<&vampire_python21.Py_FlushLine>]
200DAB6E  |.  85C0          TEST EAX,EAX
200DAB70  |.- 74 06         JE SHORT <JMP.&vampire_python21.Py_FlushConsoleOutput>              ; Jump to vampire_python21.Py_FlushConsoleOutput
200DAB72  |.  FF15 9C331720 CALL DWORD PTR DS:[<&vampire_python21.PyErr_Clear>]
200DAB78  |>- FF25 BC331720 JMP DWORD PTR DS:[<&vampire_python21.Py_FlushConsoleOutput>]
200DAB7E  \>  C3            RETN 

所以我认为很清楚,签名将是以下的一些变体 int (const char*, int /它始终是 256 并且与这些 python 方法中的常量匹配/, PyObject * /*getDict */, PyObject *的返回)

但是我崩溃了每当我尝试访问(或将)假定的 pyObjects 作为 pyobject 时,即用

printf("%s\n", PyString_AsString(PyObject_Str(pyobj))); 打印它们;

所以我想打印该字符串(我知道它是一个字符串,因为它来自文件)。

__declspec (dllexport) int PyRun_ConsoleString(const char *str, int typeOfExpression, PyObject * globals, PyObject * locals){

    printf("%s\n", str);
    fflush(stdout);
    return 0;
}

printf("%s\n",str) 打印预期的字符串 'qwerty "what"' 好的,这就是文件中的内容

printf("%s 1 \n", str) 打印 ' 1 rty "what"' ? !?

任何有关查找返回值类型的帮助也将不胜感激。其程序集是:

CPU Disasm
Address   Hex dump          Command                                 Comments
1E153160  /$  8B4424 10     MOV EAX,DWORD PTR SS:[ARG.4]
1E153164  |.  8B4C24 0C     MOV ECX,DWORD PTR SS:[ARG.3]
1E153168  |.  8B5424 08     MOV EDX,DWORD PTR SS:[ARG.2]
1E15316C  |.  6A 00         PUSH 0
1E15316E  |.  50            PUSH EAX
1E15316F  |.  8B4424 0C     MOV EAX,DWORD PTR SS:[ARG.1]
1E153173  |.  51            PUSH ECX
1E153174  |.  68 B825191E   PUSH OFFSET 1E1925B8                    ; ASCII "<string>"
1E153179  |.  52            PUSH EDX                                ; /Arg2 => [ARG.2]
1E15317A  |.  50            PUSH EAX                                ; |Arg1 => [ARG.1]
1E15317B  |.  E8 D0030000   CALL PyParser_SimpleParseConsoleString  ; \vampire_python21_backup.PyParser_SimpleParseConsoleString
1E153180  |.  83C4 08       ADD ESP,8
1E153183  |.  50            PUSH EAX
1E153184  |.  E8 37010000   CALL 1E1532C0
1E153189  |.  83C4 14       ADD ESP,14
1E15318C  \.  C3            RETN

尽管我怀疑该值来自子函数。

I'm trying to reverse engineer a function over which i have no source, and is protected by a anti debugger.

Anyway, i'm interested the function PyRun_ConsoleString in the caller assembly is:

CPU Disasm
Address   Hex dump          Command                                                             Comments
200DAB20  /$  68 D8961A20   PUSH OFFSET 201A96D8                                                ; ASCII "__main__"
200DAB25  |.  FF15 B0331720 CALL DWORD PTR DS:[<&vampire_python21.PyImport_AddModule>]
200DAB2B  |.  83C4 04       ADD ESP,4
200DAB2E  |.  85C0          TEST EAX,EAX
200DAB30  |.  74 4C         JE SHORT 200DAB7E
200DAB32  |.  50            PUSH EAX
200DAB33  |.  FF15 8C331720 CALL DWORD PTR DS:[<&vampire_python21.PyModule_GetDict>]
200DAB39  |.  50            PUSH EAX
200DAB3A  |.  50            PUSH EAX
200DAB3B  |.  8B4424 10     MOV EAX,DWORD PTR SS:[ESP+10]
200DAB3F  |.  68 00010000   PUSH 100
200DAB44  |.  50            PUSH EAX
200DAB45  |.  FF15 90331720 CALL DWORD PTR DS:[<&vampire_python21.PyRun_ConsoleString>]
200DAB4B  |.  83C4 14       ADD ESP,14
200DAB4E  |.  85C0          TEST EAX,EAX
200DAB50  |.  75 08         JNE SHORT 200DAB5A
200DAB52  |.  FF15 94331720 CALL DWORD PTR DS:[<&vampire_python21.PyErr_Print>]
200DAB58  |.- EB 1E         JMP SHORT <JMP.&vampire_python21.Py_FlushConsoleOutput>             ; Jump to vampire_python21.Py_FlushConsoleOutput
200DAB5A  |>  FF08          DEC DWORD PTR DS:[EAX]
200DAB5C  |.  75 0A         JNE SHORT 200DAB68
200DAB5E  |.  8B48 04       MOV ECX,DWORD PTR DS:[EAX+4]
200DAB61  |.  50            PUSH EAX
200DAB62  |.  FF51 18       CALL DWORD PTR DS:[ECX+18]
200DAB65  |.  83C4 04       ADD ESP,4
200DAB68  |>  FF15 98331720 CALL DWORD PTR DS:[<&vampire_python21.Py_FlushLine>]
200DAB6E  |.  85C0          TEST EAX,EAX
200DAB70  |.- 74 06         JE SHORT <JMP.&vampire_python21.Py_FlushConsoleOutput>              ; Jump to vampire_python21.Py_FlushConsoleOutput
200DAB72  |.  FF15 9C331720 CALL DWORD PTR DS:[<&vampire_python21.PyErr_Clear>]
200DAB78  |>- FF25 BC331720 JMP DWORD PTR DS:[<&vampire_python21.Py_FlushConsoleOutput>]
200DAB7E  \>  C3            RETN 

So i thought it was pretty clear cut the signature would be some variant of
int (const char*, int /it is always 256 and that matchs with a constant in these python methods/, PyObject * /*return of getDict */, PyObject *)

However i'm getting crashes whenever i try to access (or treat) the presumed pyObjects as pyobject, ie, print them with

printf("%s\n", PyString_AsString(PyObject_Str(pyobj)));

So I thought to print the string (that i know it's a string since it comes from a file).

__declspec (dllexport) int PyRun_ConsoleString(const char *str, int typeOfExpression, PyObject * globals, PyObject * locals){

    printf("%s\n", str);
    fflush(stdout);
    return 0;
}

printf("%s\n",str) prints the expected string 'qwerty "what"' ok, it's what is in the file

printf("%s 1 \n", str) prints ' 1 rty "what"' ?!?

Any assistance in finding the return value type would be much appreciated too. The assembly for that is:

CPU Disasm
Address   Hex dump          Command                                 Comments
1E153160  /$  8B4424 10     MOV EAX,DWORD PTR SS:[ARG.4]
1E153164  |.  8B4C24 0C     MOV ECX,DWORD PTR SS:[ARG.3]
1E153168  |.  8B5424 08     MOV EDX,DWORD PTR SS:[ARG.2]
1E15316C  |.  6A 00         PUSH 0
1E15316E  |.  50            PUSH EAX
1E15316F  |.  8B4424 0C     MOV EAX,DWORD PTR SS:[ARG.1]
1E153173  |.  51            PUSH ECX
1E153174  |.  68 B825191E   PUSH OFFSET 1E1925B8                    ; ASCII "<string>"
1E153179  |.  52            PUSH EDX                                ; /Arg2 => [ARG.2]
1E15317A  |.  50            PUSH EAX                                ; |Arg1 => [ARG.1]
1E15317B  |.  E8 D0030000   CALL PyParser_SimpleParseConsoleString  ; \vampire_python21_backup.PyParser_SimpleParseConsoleString
1E153180  |.  83C4 08       ADD ESP,8
1E153183  |.  50            PUSH EAX
1E153184  |.  E8 37010000   CALL 1E1532C0
1E153189  |.  83C4 14       ADD ESP,14
1E15318C  \.  C3            RETN

though i suspect the value comes from a subfunction.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

世态炎凉 2024-10-28 04:54:34

嗯,不错的拼图。
前言:
printf("%s 1 \n", str) 打印 ' 1 rty "what"' ?!?
...在我看来就像您在控制台上看到的那样,对吧?)是:

qwerty "what"

后跟 return (无换行),覆盖为:

' 1 '

然后 \n

这表明您提供的字符串(来自文件?)包括终止返回字符。

Hmmm, nice puzzle.
FWIW:
printf("%s 1 \n", str) prints ' 1 rty "what"' ?!?
... looks to me like what you are seeing on the console, right?) is:

qwerty "what"

followed by return (no line feed), overwritten by:

' 1 '

then \n

This suggests that the string you are supplying (from a file?) includes a terminating return character.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文