The basic of developing iOS Tweak (Part 4/4)

Witsarut L.
INCOGNITO LAB
Published in
5 min readMay 15, 2019
ขั้นตอนการพัฒนา Tweak

ใน Part 2 และ Part 3 เราได้พูดถึงและอธิบายวิธีการวิเคราะห์และทำ prototype Tweak จนถึงขั้นตอนที่ 4 แล้ว สำหรับใน Part นี้จะเป็นขั้นตอนที่ 5 ซึ่งเป็นขั้นตอนที่จะนำ prototype ที่ได้มาพัฒนาเป็น Tweak โดยใช้ Theos กันครับ

ก่อนจะเริ่มลงมือ เรามาทำความรู้จักกับ Theos กันซักเล็กน้อยก่อน

Theos

Theos

Theos คือ platform ที่สร้างมาเพื่อให้สามารถจัดการ, พัฒนา หรือ deploy iOS application ได้ โดยไม่ต้องพึ่งพา Xcode ซึ่ง Theos support ระบบปฏิบัติการ MacOS, Linux หรือแม้กระทั่ง Windows อีกทั้ง Theos เองก็มี template ไว้ช่วยในการพัฒนา Tweak ให้สามารถทำได้ง่ายยิ่งขึ้น (และ Tweak ส่วนใหญ่ใน Cydia ก็ใช้ Theos ในการพัฒนา)

Theos จะใช้ syntax ที่เรียกว่า Logos ในการพัฒนา Tweak โดย Logos จะมีลักษณะที่เหมือนกันกับ Objective-C แต่จะมีการเพิ่ม feature บางอย่างที่ทำให้สามารถ hook method/function ได้ง่ายยิ่งขึ้น

สำหรับวิธีการติดตั้งและตั้งค่า Theos สามารถดูวิธีการได้ที่นี่

ในขั้นตอนสุดท้ายนี้ จะเป็นการ compile และสร้างไฟล์ package ของ Tweak เพื่อที่จะสามารถนำไปติดตั้งบนอุปกรณ์หรือ upload ไปยัง repository เพื่อเผยแพร่ให้คนอื่นสามารถติดตั้งได้ โดยวิธีการที่จะพูดถึงต่อไปนี้จะเป็นวิธีการที่ Tweak ส่วนใหญ่ที่เราใช้งานอยู่ ได้ถูกสร้างขึ้นมา

เกริ่นนำมาเยอะแล้ว เรามาเริ่มพัฒนา Tweak ของเราเองบ้างดีกว่า โดยนำ prototype ที่ได้จาก Part 3 มาพัฒนาให้เป็น Tweak จริง ๆ กันเลยครับ

ขั้นตอนที่ 5 พัฒนา Tweak โดยใช้ Theos

ก่อนที่จะเขียน code เพื่อ hook method/function เราจะต้อง generate template ของ Tweak ขึ้นมาซะก่อน

สร้าง Theos project

ไปยังโฟลเดอร์ที่ต้องการให้เป็น working directory ของ Tweak จากนั้นทำการ execute ไฟล์ nic.pl (New Instance Creator) ของ Theos ซึ่งเป็นไฟล์ที่ใช้สร้าง template

execute ไฟล์ nic.pl เพื่อสร้าง template ของ Tweak

ที่ option Choose a Template ให้เลือก template ที่ 13 (iphone/tweak) เพื่อสร้าง Tweak (template อื่น ๆ ไว้ใช้ทำอะไรดูได้จากที่นี่)

สำหรับ optionProject Name, Package Name และAuthor/Maintainer Name จะเป็นค่าอะไรก็ได้

แต่ส่วนที่สำคัญคือ option MobileSubstrate Bundle filter ซึ่งจะต้องเป็นชื่อ bundle ของ application เป้าหมาย (ดูได้จากไฟล์ Info.plist ตามที่ได้พูดถึงไปใน Part 2) ในที่นี้คือ com.swaroop.iGoat

และอีก option ที่สำคัญ List of application to terminate upon installation จะเป็น option ที่จะให้เรากำหนดว่าเมื่อ Tweak ของเราถูกติดตั้งบนอุปกรณ์แล้ว จะให้ทำการ terminate process ของ application ไหนทิ้ง เพราะบางครั้ง Tweak จะเห็นผลเมื่อ restart application เท่านั้น ในที่นี้จะใส่เป็น executable name iGoat

เมื่อใส่ option ครบสมบูรณ์แล้ว เราจะได้โฟลเดอร์ตามชื่อ Project Name มา

โครงสร้างของ template

เมื่อเข้าไปในโฟลเดอร์ของ template จะพบกับไฟล์ตามรูป ที่ถูกสร้างขึ้นมาจาก nic.pl

โครงสร้างของ template

แล้วแต่ละไฟล์ในโฟลเดอร์เอาไว้ใช้ทำอะไรกัน?

Makefile

ไฟล์ที่ใช้เก็บข้อมูลพื้นฐานที่จำเป็นสำหรับการ compile code และสร้าง package ของ Tweak เพื่อเอาไปใช้งาน ในเบื้องต้นไฟล์จะมี content ดังรูป

content ของไฟล์ Makefile

include คือการ include ไฟล์ที่จำเป็นในการ compile Tweak ของ Theos ในส่วนนี้เราไม่จำเป็นต้องแก้ไข

TWEAK_NAME คือชื่อของ Tweak ที่เราใส่ไปตอนที่สร้าง template

ez_igoat_tweak_FILES คือ Source file (ไฟล์ code) ของ Tweak

after-install คือ Parameter ที่ใช้สำหรับระบุว่าหลังจาก install Tweak บนอุปกรณ์เสร็จแล้ว จะให้ execute คำสั่งอะไรต่อไป ในกรณีนี้คือการ terminate process iGoat ซึ่งคำสั่งที่ปรากฎอยู่ก็มาจากค่าที่เราใส่ไปตอนที่สร้าง template นั่นเอง

นอกจาก parameter ที่พูดถึงไปแล้ว เราสามารถกำหนดค่าอื่น ๆ เพิ่มเติมได้อีกตามความต้องการโดยสามารถดูรายละเอียดได้ที่นี่

control

คือไฟล์ข้อมูลพื้นฐานของ Tweak package โดยข้อมูลพวกนี้จะไปปรากฎอยู่บน Cydia ให้ผู้ใช้งานได้ทราบ

content ของไฟล์ control

ซึ่ง parameter โดยส่วนใหญ่ในไฟล์นี้ เราสามารถแก้ไขเป็นค่าอะไรก็ได้ตามต้องการ สำหรับความหมายของแต่ละ parameter สามารถดูได้จากที่นี่

Note: ค่าของ Parameter Package ด้านหลังสุดจะต้องไม่ประกอบไปด้วยสัญลักษณ์ เพราะฉะนั้นจะต้องเปลี่ยนค่าเป็น com.yourcompany.ezigoattweak

ez_igoat_tweak.plist

คือไฟล์ plist ที่ใช้ระบุ scope ของ Tweak ว่า เป้าหมายของ Tweak นี้คือ bundle, class หรือไฟล์ executable ไหน ในเบื้องต้นระบุแค่ bundle ก็เพียงพอ แต่เราก็สามารถระบุ class, ไฟล์ executable ได้เช่นเดียวกัน

content ของไฟล์ ez_igoat_tweak.plist

Tweak.xm

และสำหรับไฟล์ที่สำคัญไฟล์สุดท้าย คือไฟล์ Tweak.xm ที่ใช้เก็บ code หลักของ Tweak นั่นเอง โดยไฟล์ที่ถูกสร้างขึ้นมาจะมี content ที่บอกวิธีการเขียน code โดยใช้ Logos syntax เพื่อ hook Objective-C method ไว้คร่าว ๆ แล้ว

content ของไฟล์ Tweak.xm

ลงมือเขียน code

สำหรับการเขียน code โดยใช้ Logos syntax เพื่อทำการ hook method/function นั่น จะมีสิ่งที่เรียกว่า directive ที่จะช่วยให้การเขียน code เพื่อ hook method/function ทำได้ง่ายขึ้นอยู่ โดย directive ที่สำคัญจะมีดังต่อไปนี้

%hookใช้สำหรับเปิด block ของ code เพื่อ hook Objective-C method โดยจะต้องระบุ class ของ method ที่ต้องการจะ hook และเมื่อสิ้นสุด code ส่วนที่ทำการ hook แล้ว จะต้องปิด block ด้วย %end เสมอ

%orig — ใช้สำหรับเรียกใช้งาน implementation เดิมของ method ที่ถูก hook

%logใช้สำหรับบันทึก string ที่ต้องการไปยัง system log ของอุปกรณ์ โดยสามารถที่จะบันทึก class, argument ของ method ที่ถูก hook ได้เช่นกัน

%newใช้สำหรับเพิ่ม method ใหม่ไปใน class ที่ถูก hook

นอกจาก diractive ที่สำคัญและต้องใช้เป็นประจำข้างต้นแล้ว Logos ก็ยังมี derective ตัวอื่น ๆ อีกที่อาจทำให้การพัฒนา Tweak ง่ายขึ้นไปอีกขั้น โดยสามารถดูรายละเอียดเพิ่มเติมได้ที่นี่

เมื่อรู้วิธีการใช้งาน directive แล้ว เราก็สามารถนำ prototype Tweak จาก Part 3 มาแปลงเป็น Logos syntax ได้ไม่ยาก

prototype Tweak จาก Part 3

แต่จะมีสิ่งหนึ่งที่ต้องทำก่อนคือ หากเราต้องการจะเรียกใช้งาน method, variable และ property ใด ๆ ของ class ที่จะ hook เราจะต้องประกาศ class, method, variable และ property นั้น ๆ ไว้ในไฟล์ header ด้วย เพื่อให้ linker รู้ว่า method, variable และ property นั้นมีอยู่ และจะ compile ได้ผ่าน

สำหรับในกรณีนี้เรามี variable และ property ของ class PersonalPhotoStorageVC ที่ต้องเรียกใช้งานคือ _pw และ theTextField ตามลำดับ

Note: method, variable และ property ที่ต้องการจะ hook ไม่จำเป็นต้องถูกประกาศในไฟล์ header

ไฟล์ header PersonalPhotoStorageVC.h

ต่อไปก็จะเป็นการเขียน code ไปในไฟล์ Tweak.xm โดยใช้ Logos syntax

code ในไฟล์ Tweak.xm

บรรทัดที่ 1 คือการ import ไฟล์ header PersonalPhotoStorageVC.h

บรรทัดที่ 3 คือการเปิด block ของ code โดยใช้ %hook และตามด้วยชื่อ class ที่จะ hook

บรรทัดที่ 6 คือการเริ่มต้น hook method viewDidLoad

บรรทัดที่ 7 คือการเรียกใช้งาน implementation เดิมของ method viewDidLoad

บรรทัดที่ 8 คือการเปลี่ยน text ของ text field ให้แสดง password โดย [self valueForKey:@”_pw”] คือการเข้าถึงค่าที่ถูกเก็บไว้ที่ instance variable _pw

บรรทัดที่ 13 คือการปิด block ของ code ที่ทำหน้าที่ hook โดยใช้ %end

Compile และสร้าง package

เมื่อแก้ไขและสร้างไฟล์ต่าง ๆ เสร็จเรียบร้อยแล้ว ขั้นตอนต่อไปก็คือการ compile วิธีการคือให้ไปที่โฟลเดอร์ของ Tweak และใช้คำสั่ง make หากไม่มีการกำหนด architecture ที่ต้องการ support ใน Makefile โดย default แล้ว Tweak จะถูก compile เพื่อ support architecture ทั้งแบบ armv7 และ arm64

compile Tweak เสร็จสมบูรณ์

และไฟล์ผลลัพธ์จากการ compile จะอยู่ใน path .theos/obj/debug/

โครงสร้างของโฟลเดอร์ .theos

จากนั้นใช้คำสั่ง make package เพื่อสร้างไฟล์ package deb (Debian package) โดยไฟล์ที่ได้ จะเป็นไฟล์ที่สามารถนำไปติดตั้งในอุปกรณ์ได้ เมื่อสร้างไฟล์ package เสร็จสมบูรณ์ ตัวไฟล์จะอยู่ในโฟลเดอร์ packages

ใช้คำสั่ง make package เพื่อสร้างไฟล์ package deb

หากลอง extract ไฟล์ package deb ออกมา ก็จะพบกับโฟลเดอร์ Library ที่มีไฟล์ dylib ซึ่งเป็นหัวใจหลักของ Tweak

โครงสร้างของไฟล์ package deb
ใช้คำสั่ง file และ otool ในการตรวจสอบไฟล์ dylib

ติดตั้ง Tweak บนอุปกรณ์

Copy ไฟล์ package deb ที่ได้ไปยังอุปกรณ์และใช้คำสั่งต่อไปนี้เพื่อติดตั้ง Tweak บนอุปกรณ์

ใช้คำสั่ง dpkg ติดตั้ง Tweak

-i = ติดตั้ง package

และหากทดสอบใช้งาน application iGoat ก็จะพบว่า Tweak ทำงานได้สมบูรณ์ ตามเป้าหมายที่ได้วางไว้

ผลลัพธ์จากการติดตั้ง Tweak

เมื่อลองทดสอบดูข้อมูลของ Tweak บน Cydia จะเห็นว่า ข้อมูลจากไฟล์ control จะถูกนำมาแสดง

ข้อมูลพื้นฐานของ Tweak

ทิ้งท้าย…

เมื่อเข้าใจวิธีการพัฒนา Tweak แล้ว จะทำให้เราสามารถที่จะไปอ่าน Tweak ที่ถูกพัฒนาโดยคนอื่นอย่างเข้าใจ อีกทั้งสามารถแก้ไขหรือสร้าง Tweak ของตัวเองขึ้นมาใช้งานได้

สำหรับในบทความนี้จะเป็นการพูดถึงการสร้าง Tweak ของ store application เท่านั้น สำหรับการทำ Tweak ของ system application จะมีความซับซ้อนมากกว่าพอสมควร โดยจะมีกล่าวถึงในบทความถัด ๆ ไปครับ

ขอจบ basic แต่เพียงเท่านี้…

--

--

Witsarut L.
INCOGNITO LAB

Penetration tester, security researcher at Incognito Lab.