บทนำ (Overview)
บทความนี้นำเสนอวิธีการหลบหลีกหน้า “login” โดยใช้วิธีการ “Debugging” จากโปรแกรม “GDB” ซึ่งหลักการคือค้นหา “Method” ที่หน้าสนใจเกี่ยวกับการ “login” จากนั้นพยายาม หาส่วนการตัดสินใจของ “Register” และปรับเปลี่ยนค่าให้สามารถผ่านเงื่อนไขการตรวจสอบไปได้ โดยปกติเป็นค่าเงื่อนไขของ จริง (True) หรือเท็จ (False) ดังต่อไปนี้
ขั้นตอน (Steps)
- ติดตั้ง “GDB” บน “iOS”
- เปิดโปรแกรมที่ต้องการทดสอบขึ้นมา
- จากนั้นตรวจสอบ “ProcessId” ของโปรแกรมที่เราเปิดขึ้นมาว่ามีหมายเลขอะไรโดยใช้คำสั่งดังนี้
//ps aux | grep [ชื่อโปรแกรมที่ค้นหา] ps aux | grep iVulner
- เราใช้ “GDB” เพื่อเชื่อมต่อไปยัง “ProcessId” ดังกล่าวโดยใช้คำสั่ง
//gdb -p [processId] gdb -p 78428
- โดยปกติถ้าเราเรียกใช้งาน “Method” จะต้องใช้เราจะเขียน “code” ดังนี้
-
การเรียกใช้งาน "Method" (ขึ้นอยู่กับ Class method หรือ Instance Method ด้วย)
[foo bar:variable]
-
แต่ถ้า "Compile" ไปแล้วจะถูกแปลงเป็นคำสั่ง
objc_msgSend (foo, @selector(bar:),variable) // foo แต่เดิมเป็น Instance แต่ในเวลา Runtime คือ pointer ที่ชี้ไปยัง Instant ของ Class ที่จะรับ Message // bar แต่เดิมเป็น Method แต่ในเวลา Runtime คือ Selector ของ Method ที่ใช้สำหรับจัดการ Messages // variable ยังเป็น argument ของ method
-
- ก่อนที่จะวิเคราะห์โปรแกรมในขณะใช้งาน (Run-time analysis) เราจะต้องทราบข้อมูลเบื้องต้นเกี่ยวกับ ชื่อของ “Class” และ “Method” เสียก่อน โดยใช้วิธีการดังนี้
- จากวิธีการดังกล่าวข้างต้นสามารถได้ชื่อ “Class” และ “Method” ที่น่าสนใจดังนี้ “cmdLogin” น่าจะเป็นปุ่มสำหรับการกด “Login”
@Interface ViewController : UIViewController { //Instance Variables UITextField* _txtUser; UITextField* _txtPass; } //Properties @property (weak,nonatomic) UITextField* txtUser; // = _txtUser @property (weak,nonatomic) UITextField* txtPass; // = _txtPass //Methods - (void) cmdLogin:(id)arg0; - (id) txtUser; - (void) setTxtUser:(id)arg0; - (id) txtPass; - (void) setTxtPass:(id)arg0; - (void) didReceiveMemoryWarning; - (void) viewDidLoad; - (void) .cxx_destruct; - (id) init; @end
- เริ่มต้นการตั้งค่าตำแหน่งที่จะต้องหยุดให้กับ “Debugger (Breakpoints)” โดยใช้คำสั่งดังข้าง เราสนจที่ใส่ Breakpoints ให้กับ “cmdLogin” นั้นหมายความจะต้องกดปุ่ม “Submit” แล้วโปรแกรมจะต้องมาหยุดที่ “Breakpoints” ที่ตั้งเอาไว้
//b [method]: หรือ //break [mobile]: b cmdLogin:
- ถ้ามีชื่อ Method ซ้ำกันในหลาย “Class” โปรแกรมจะแสดงออกมาทั้งหมด ให้เราเลือกตามหมายเลขข้างหน้า
- เมื่อเราเลือกเสร็จสิ้น สามารถตรวจสอบ “Breakpoints” ที่เราเลือกได้ (สามารถเลือกได้หลาย ๆ “Breakpoints”) โดยใช้คำสั่ง
info breakpoints
- ในทำนองเดียว เราก็สามารถลบ “Breakpoints” ออกได้เช่นกันโดยใช้คำสั่ง
//delete [num] //delete [num1] [num2] [numN] delete 1 2
- ที่นี้ย้อนกลับมาที่ “Breakpoints” ที่เราเลือก ที่หน้าจอโปรแกรมบน “Mobile” ตอนนี้จะยังไม่สามารถกดอะไรได้ ให้ใช้คำสั่ง
c //หรือ continue
- เราสามารถใช้คำสั่ง “continue” หรือ “c” ได้เรื่อย ๆ ตราบเท่าจำนวนที่ “Breakpoints” เราได้ตั้งเอาไว้ เมื่อเรียกใช้งานคำสั่งดังกล่าวแล้วจะเห็นได้ว่าที่หน้าจอ “iOS” ของเราสามารถที่จะกดปุ่ม หรือแก้ไข “username” และ “password” ได้ ให้เรากดปุ่ม “SUBMIT”
- ย้อนกลับมาที่ “Breakpoints” พอเรามาถึง “Breakpoints” ของ “Method” ที่เราสนใจแล้วนั้น เราสามารถตรวจสอบได้ว่ามี “Instruction” (คำสั่งในแต่ละบรรทัด) ถัดไปอะไรที่หน้าสนใจบ้าง โดยใช้คำสั่ง
disas
- เราจะพบว่ามีเลขหมายเลข “Address” ของแต่ละ “Instruction” มาให้เราก็สามารถตั้ง “Breakpoints” ในแต่ละ “Instruction” ได้เช่นกัน แต่ต่างกันเล็กน้อย โดยจะต้องมี * นำหน้า “Address” เสมอ จากการ “Dump assembler” เราสนใจ “CMP instruction” 2 ตัว จึงนำมา ฺ”Breakpoint” ตามข้างล่าง
//break *[address] b *0x0006a4fc b *0x0006a58c
- เมื่อ Breakpoints เสร็จสิ้นให้ใช้คำสั่ง “c” เพื่อประมวลผลไปยัง “Breakpoints” ต่อไป
- จากนั้นใช้คำสั่งเพื่อ “set” ค่า $r0 =1 กับทั้งสอง “Breakpoints” ดังนี้
set $r0 = 1
- เพิ่มเติมจากข้างต้นเกี่ยวกับ “$r0” (ดูเพิ่มเติมได้จาก https://en.wikipedia.org/wiki/Calling_convention)
ARM registers Description r15 The program counter r14 The link register. (The BL instruction, used in a subroutine call, stores the return address in this register). r13 The stack pointer. (The Push/Pop instructions in “Thumb” operating mode use this register only). r12 The Intra-Procedure-call scratch register. r4 to r11 Used to hold local variables. r0 to r3 Used to hold argument values passed to a subroutine, and also hold results returned from a subroutine. Registers Description r0 Self จากตัวอย่างคือ foo แต่เดิมเป็น Instance แต่ในเวลา Runtime คือ point ที่ชี้ไปยัง Instant ของ Class ที่จะรับ Message r1 op จากตัวอย่างคือ bar แต่เดิมเป็น Method แต่ในเวลา Runtime คือ Selector ของ Method ที่ใช้สำหรับจัดการ Messages r2 ตัวแปรต่าง ๆ ที่ส่งผ่าน Argument - เพิ่มเติม “CMP instruction” ทำหน้าที่เปรียบเทียบ 2 “operands” (“Operators” คือ สัญลักษณ์พิเศษที่ทำหน้าที่แทนการคำนวณ อย่างการบวกและการคูณ ค่าที่ใช้กับ “Operator” นั้นเรียกว่า “Operands”) โดยทั่วไปถูกใช้ในการประมวลผลส่วนของเงื่อนไข (สามารถติดตามเพิ่มเติมได้ที่ https://www.tutorialspoint.com/assembly_programming/assembly_conditions.htm)
- กลับไปที่หน้าจอ “iOS” พบว่าสามารถเข้าถึงหน้า “login” ได้ แม้จะใส่ “username” และ “password” ที่ไม่ถูกต้องก็ตาม