title: How can printf corrupt strings?
body: <p>I'm trying to reverse engineer a function over which i have no source, and is protected by a anti debugger. </p>
  
  <p>Anyway, i'm interested the function PyRun_ConsoleString in  the caller assembly is:</p>
  
  <pre><code>CPU Disasm
  Address   Hex dump          Command                                                             Comments
  200DAB20  /$  68 D8961A20   PUSH OFFSET 201A96D8                                                ; ASCII "__main__"
  200DAB25  |.  FF15 B0331720 CALL DWORD PTR DS:[&lt;&amp;vampire_python21.PyImport_AddModule&gt;]
  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:[&lt;&amp;vampire_python21.PyModule_GetDict&gt;]
  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:[&lt;&amp;vampire_python21.PyRun_ConsoleString&gt;]
  200DAB4B  |.  83C4 14       ADD ESP,14
  200DAB4E  |.  85C0          TEST EAX,EAX
  200DAB50  |.  75 08         JNE SHORT 200DAB5A
  200DAB52  |.  FF15 94331720 CALL DWORD PTR DS:[&lt;&amp;vampire_python21.PyErr_Print&gt;]
  200DAB58  |.- EB 1E         JMP SHORT &lt;JMP.&amp;vampire_python21.Py_FlushConsoleOutput&gt;             ; Jump to vampire_python21.Py_FlushConsoleOutput
  200DAB5A  |&gt;  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  |&gt;  FF15 98331720 CALL DWORD PTR DS:[&lt;&amp;vampire_python21.Py_FlushLine&gt;]
  200DAB6E  |.  85C0          TEST EAX,EAX
  200DAB70  |.- 74 06         JE SHORT &lt;JMP.&amp;vampire_python21.Py_FlushConsoleOutput&gt;              ; Jump to vampire_python21.Py_FlushConsoleOutput
  200DAB72  |.  FF15 9C331720 CALL DWORD PTR DS:[&lt;&amp;vampire_python21.PyErr_Clear&gt;]
  200DAB78  |&gt;- FF25 BC331720 JMP DWORD PTR DS:[&lt;&amp;vampire_python21.Py_FlushConsoleOutput&gt;]
  200DAB7E  \&gt;  C3            RETN 
  </code></pre>
  
  <p>So i thought it was pretty clear cut the signature would be some variant of
  int (const char*, int /<em>it is always 256 and that matchs with a constant in these python methods</em>/, PyObject * /*return of getDict */, PyObject *)</p>
  
  <p>However i'm getting crashes whenever i try to access (or treat) the presumed pyObjects as pyobject, ie, print them with </p>
  
  <p>printf("%s\n", PyString_AsString(PyObject_Str(pyobj))); </p>
  
  <p>So I thought to print the string (that i know it's a string since it comes from a file).</p>
  
  <pre><code>__declspec (dllexport) int PyRun_ConsoleString(const char *str, int typeOfExpression, PyObject * globals, PyObject * locals){
  
      printf("%s\n", str);
      fflush(stdout);
      return 0;
  }
  </code></pre>
  
  <p>printf("%s\n",str) prints the expected string 'qwerty "what"' ok, it's what is in the file</p>
  
  <p>printf("%s 1 \n", str) prints ' 1 rty "what"' ?!?</p>
  
  <p>Any assistance in finding the return value type would be much appreciated too. The assembly for that is:</p>
  
  <pre><code>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 "&lt;string&gt;"
  1E153179  |.  52            PUSH EDX                                ; /Arg2 =&gt; [ARG.2]
  1E15317A  |.  50            PUSH EAX                                ; |Arg1 =&gt; [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
  </code></pre>
  
  <p>though i suspect the value comes from a subfunction.</p>