# การทำให้ Frida Script คงอยู่ถาวร

FIRERPA มอบความสามารถในการทำให้ Frida script ของคุณคงอยู่ถาวร คุณสามารถฉีดสคริปต์ได้อย่างสะดวกผ่านอินเทอร์เฟซที่เกี่ยวข้อง และตัวจัดการสคริปต์ของ FIRERPA จะจัดการสคริปต์ที่ถูกฉีดให้คุณโดยอัตโนมัติ แม้ว่าสคริปต์ของคุณจะหยุดทำงานอย่างผิดปกติหรือโปรเซสของแอปจะปิดตัวลง FIRERPA ก็จะยังคงฉีดสคริปต์ให้คุณใหม่โดยอัตโนมัติในครั้งถัดไปที่คุณเปิดแอป ฟีเจอร์นี้ถูกเพิ่มเข้ามาในเวอร์ชัน 7.80

## การติดตั้งสคริปต์

คุณสามารถใช้อินเทอร์เฟซนี้เพื่อติดตั้งสคริปต์ของคุณไปยังแอปพลิเคชันที่เกี่ยวข้อง สคริปต์ที่คุณติดตั้งไปยังแอปพลิเคชันนั้นจะถูกฉีดเข้าไปในแอปพลิเคชันทันทีหลังการติดตั้ง สคริปต์ที่ติดตั้งจะเข้าสู่ตัวจัดการสคริปต์โดยอัตโนมัติ ซึ่งจะคอยตรวจสอบและฉีดสคริปต์ใหม่ให้คุณตลอดเวลา

```{attention}
ตัวจัดการสคริปต์อนุญาตให้แต่ละแอปฉีดสคริปต์ได้เพียงหนึ่งสคริปต์ในเวลาเดียวกัน คุณไม่สามารถฉีดสคริปต์หลายตัวไปยังแอปพลิเคชันเดียวกันพร้อมกันได้
```

```python
app = d.application("com.android.settings")
app.attach_script(script, runtime=ScriptRuntime.RUNTIME_QJS, standup=5)
```

พารามิเตอร์ `script` คือเนื้อหาของ Frida script ที่คุณต้องการฉีด (รองรับ bytecode), `runtime` คือ runtime ที่สอดคล้องกัน โดยค่าเริ่มต้นคือ `qjs`, ความหมายของพารามิเตอร์ `standup` คือจะทำการฉีดหลังจากที่โปรเซสของแอปเริ่มทำงานไปแล้ว 5 วินาทีเท่านั้น (เวลาจะเริ่มนับตั้งแต่โปรเซสถูกสร้างขึ้น) พารามิเตอร์นี้มีค่าต่ำสุด 1 วินาทีและสูงสุด 300 วินาที เพื่อหลีกเลี่ยงปัญหา race condition อื่นๆ เช่น การแครชที่เกิดจากการฉีดสคริปต์เข้าไปในโปรเซสของแอปเร็วเกินไป ในโหมด spawn พารามิเตอร์นี้ควรเป็น 0 เสมอ

อินเทอร์เฟซนี้ยังรองรับการฉีดในโหมด spawn แต่โปรดทราบว่าการใช้โหมด spawn อาจขัดจังหวะขั้นตอนการทำงานของ UI ของคุณ (หากคุณต้องการ操作 UI ไปพร้อมกัน) เพราะเมื่อคุณใช้โหมด spawn ในกรณีที่สคริปต์ที่ฉีดเกิดข้อผิดพลาดหรือแอปปิดตัวลง โหมดนี้จะเรียกแอปขึ้นมาใหม่โดยอัตโนมัติ ซึ่งจะรบกวนการทำงานบนหน้าจอของคุณ หากคุณต้องการใช้โหมด spawn โปรดใช้พารามิเตอร์ดังต่อไปนี้

```python
app = d.application("com.android.settings")
app.attach_script(script, runtime=ScriptRuntime.RUNTIME_QJS, spawn=True, standup=0)
```

โปรดทราบว่าโหมด spawn แตกต่างจากโหมดปกติ ในโหมดปกติ หากแอปปิดตัวลงด้วยเหตุผลบางประการ โหมดปกติจะรอจนกว่าแอปจะเริ่มทำงานอีกครั้งจึงจะทำการฉีด และจะไม่เปิดแอปขึ้นมาเอง ดังนั้นคุณอาจต้องเปิดแอปด้วยตนเองผ่านโค้ดหรือด้วยมือเพื่อให้การฉีดดำเนินต่อไป ในขณะที่โหมด spawn แม้แอปจะปิดตัวลง ก็จะเปิดแอปขึ้นมาใหม่และทำการฉีดโดยอัตโนมัติ

## การยกเลิกการติดตั้ง

อินเทอร์เฟซนี้จะลบ Frida script ที่ติดตั้งไว้ในแอปพลิเคชันออก สคริปต์ดังกล่าวจะถูกถอดออกจากโปรเซสของแอปด้วย และในขณะเดียวกัน ตัวจัดการสคริปต์ของ FIRERPA ก็จะหยุดตรวจสอบสถานะของสคริปต์นั้น และจะไม่ดำเนินการฉีดใหม่หลังจากที่สคริปต์เกิดข้อผิดพลาดอีกต่อไป

```python
app = d.application("com.android.settings")
app.detach_script()
```

## การตรวจสอบว่าติดตั้งแล้วหรือไม่

อินเทอร์เฟซนี้ใช้เพื่อตรวจสอบว่าแอปพลิเคชันได้ติดตั้งสคริปต์แล้วหรือไม่ คุณสามารถใช้สถานะนี้เพื่อตรวจสอบว่าจำเป็นต้องติดตั้งใหม่หรือไม่

```python
app = d.application("com.android.settings")
app.is_attached_script()
```

## การตรวจสอบว่าฉีดแล้วหรือไม่

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

```python
app = d.application("com.android.settings")
app.is_script_alive()
```

## การดูบันทึกของสคริปต์

คุณสามารถดูบันทึกคอนโซลที่เกี่ยวข้อง เช่น `console.log` ในสคริปต์ของคุณ รวมถึงข้อความแสดงข้อผิดพลาดของสคริปต์ได้ แต่คุณต้องตั้งค่าล่วงหน้าเมื่อเริ่มต้น โปรดดูบท `การดูบันทึก` เพื่อเรียนรู้วิธีการตั้งค่าไฟล์บันทึก ด้านล่างนี้เราจะสมมติว่าคุณได้ตั้งค่าไฟล์บันทึกเป็น `/data/local/tmp/server.log` อย่างถูกต้องแล้ว ดังนั้น เมื่อต้องการดูบันทึกของสคริปต์ ให้รันคำสั่งต่อไปนี้ ซึ่งจะกรองข้อมูลบันทึกทั้งหมดของสคริปต์ที่ถูกฉีดออกมา คุณยังสามารถใช้คำสั่งอื่นๆ เช่น `tail -f` เพื่อติดตามบันทึกอย่างต่อเนื่องได้

```bash
grep SCRIPT /data/local/tmp/server.log
```

## การคงอยู่ถาวรแบบออฟไลน์

การคงอยู่ถาวรแบบออฟไลน์หมายถึงคุณสามารถวาง FRIDA script ของคุณเป็นไฟล์กำหนดค่าไว้บนโทรศัพท์ และ FIRERPA จะโหลด FRIDA script ของคุณโดยอัตโนมัติหลังจากที่เริ่มทำงาน คุณไม่จำเป็นต้องใช้ API ข้างต้นเพื่อทำการฉีดหรือยกเลิกเลย เพียงแค่เขียนไฟล์สคริปต์ในรูปแบบที่กำหนดและวางไว้ในไดเรกทอรีที่ระบุ ฟีเจอร์นี้รองรับการตรวจสอบไดเรกทอรี การโหลดแบบเรียลไทม์ รวมถึงการถอนการติดตั้งและอัปเดตสคริปต์ การแก้ไขโดยตรงในไดเรกทอรีของสคริปต์ก็จะถูกนำไปใช้แบบเรียลไทม์เช่นกัน ด้านล่างนี้คือตัวอย่างการกำหนดค่าการคงอยู่ถาวรของสคริปต์ในรูปแบบ YAML อย่างง่าย เนื้อหาสคริปต์ของการกำหนดค่าด้านล่างนี้คือ `console.log("Hello From Yaml Script")`

```yaml
enable: true
application: "com.android.settings"
version: "2.10"
user: 0
runtime: "qjs"
script: !!binary "Y29uc29sZS5sb2coIkhlbGxvIEZyb20gWWFtbCBTY3JpcHQiKQ=="
emit: "http://myserver/reportData"
encode: "none"
standup: 10
spawn: false
```

คำอธิบายโดยละเอียดของแต่ละรายการในการกำหนดค่าสคริปต์ตัวอย่างข้างต้น

| ฟิลด์       | คำอธิบาย                                                              |
|------------|-----------------------------------------------------------------------|
| enable     | เปิดใช้งานสคริปต์นี้หรือไม่                                           |
| application| ID ของแอปพลิเคชันที่จะฉีดสคริปต์ (เช่น com.android.setting)             |
| version    | เวอร์ชันของแอปพลิเคชันที่สคริปต์รองรับ ("N/A" หมายถึงไม่จำกัดเวอร์ชัน)   |
| user       | หากเป็นแอปโคลน โปรดระบุ ID ผู้ใช้ของแอปโคลน (โดยปกติคือ 999)            |
| script     | เนื้อหาสคริปต์ในรูปแบบ base64 รองรับข้อความหรือไบนารี (โปรดเขียนตามเทมเพลต) |
| runtime    | runtime ของสคริปต์ (qjs, v8)                                           |
| standup    | เวลาหน่วงในการฉีด (คำนวณจากเวลาที่โปรเซสเริ่มทำงาน)                    |
| spawn      | ใช้โหมด spawn (จะละเว้น standup)                                      |
| encode     | หากสคริปต์มีการรายงานข้อมูล ให้ระบุการเข้ารหัสที่นี่ (zlib/none)        |
| emit       | หากสคริปต์มีการรายงานข้อมูล ให้ระบุปลายทางที่นี่                       |

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับฟีเจอร์การรายงานข้อมูล `emit` โปรดดูบท `การใช้ Frida เพื่อรายงานข้อมูล`

ข้างต้นคือตัวอย่างสคริปต์แบบออฟไลน์ที่สมบูรณ์ หลังจากเขียนเสร็จแล้ว โปรดบันทึกไฟล์กำหนดค่าที่มีเนื้อหาข้างต้นเป็นไฟล์ชื่อ `{file_name}.yaml` และวางไว้ในโฟลเดอร์ `/data/usr/modules/script` ของอุปกรณ์ ระบบจะโหลดการกำหนดค่าของคุณโดยอัตโนมัติ ระบบจะตรวจจับการเปลี่ยนแปลงในไดเรกทอรี `/data/usr/modules/script` โดยอัตโนมัติ หากคุณอัปเดตหรือลบการกำหนดค่า yaml ระบบก็จะอัปเดตหรือยกเลิกการฉีดสคริปต์ของคุณโดยอัตโนมัติเช่นกัน