Frida Tutorial 1

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°

이 κ²Œμ‹œλ¬Όμ˜ μš”μ•½: https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1
APK: https://github.com/t0thkr1s/frida-demo/releases
μ†ŒμŠ€ μ½”λ“œ: https://github.com/t0thkr1s/frida-demo

Python

FridaλŠ” μ‹€ν–‰ 쀑인 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ ν•¨μˆ˜ 내에 JavaScript μ½”λ“œλ₯Ό μ‚½μž…ν•  수 있게 ν•΄μ€λ‹ˆλ‹€. ν•˜μ§€λ§Œ python을 μ‚¬μš©ν•˜μ—¬ 후크λ₯Ό ν˜ΈμΆœν•˜κ³  후크와 μƒν˜Έμž‘μš©ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

이것은 이 νŠœν† λ¦¬μ–Όμ˜ λͺ¨λ“  μ œμ•ˆλœ μ˜ˆμ œμ™€ ν•¨κ»˜ μ‚¬μš©ν•  수 μžˆλŠ” κ°„λ‹¨ν•œ python μŠ€ν¬λ¦½νŠΈμž…λ‹ˆλ‹€:

#hooking.py
import frida, sys

with open(sys.argv[1], 'r') as f:
jscode = f.read()
process = frida.get_usb_device().attach('infosecadventures.fridademo')
script = process.create_script(jscode)
print('[ * ] Running Frida Demo application')
script.load()
sys.stdin.read()

슀크립트λ₯Ό ν˜ΈμΆœν•˜μ„Έμš”:

python hooking.py <hookN.js>

python을 frida와 ν•¨κ»˜ μ‚¬μš©ν•˜λŠ” 방법을 μ•„λŠ” 것은 μœ μš©ν•˜μ§€λ§Œ, 이 μ˜ˆμ œμ—μ„œλŠ” λͺ…령쀄 frida 도ꡬλ₯Ό μ‚¬μš©ν•˜μ—¬ 직접 Fridaλ₯Ό ν˜ΈμΆœν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€:

frida -U --no-pause -l hookN.js -f infosecadventures.fridademo

Hook 1 - Boolean Bypass

μ—¬κΈ°μ—μ„œ 클래슀 _infosecadventures.fridademo.utils.PinUtil_의 boolean λ©”μ„œλ“œ (checkPin)λ₯Ό hookν•˜λŠ” 방법을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

//hook1.js
Java.perform(function () {
console.log("[ * ] Starting implementation override...")
var MainActivity = Java.use("infosecadventures.fridademo.utils.PinUtil")
MainActivity.checkPin.implementation = function (pin) {
console.log("[ + ] PIN check successfully bypassed!")
return true
}
})
python hooking.py hook1.js

λ³΄μ„Έμš”: ν•¨μˆ˜λŠ” λ§€κ°œλ³€μˆ˜λ‘œ String을 λ°›μŠ΅λ‹ˆλ‹€. μ˜€λ²„λ‘œλ“œκ°€ ν•„μš”ν•˜μ§€ μ•Šλ‚˜μš”?

Hook 2 - Function Bruteforce

Non-Static Function

클래슀의 비정적 ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ €λ©΄ λ¨Όμ € ν•΄λ‹Ή 클래슀의 μΈμŠ€ν„΄μŠ€κ°€ ν•„μš”ν•©λ‹ˆλ‹€. 그런 λ‹€μŒ, κ·Έ μΈμŠ€ν„΄μŠ€λ₯Ό μ‚¬μš©ν•˜μ—¬ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€.
이λ₯Ό μœ„ν•΄ κΈ°μ‘΄ μΈμŠ€ν„΄μŠ€λ₯Ό μ°Ύμ•„μ„œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

Java.perform(function () {
console.log("[ * ] Starting PIN Brute-force, please wait...")
Java.choose("infosecadventures.fridademo.utils.PinUtil", {
onMatch: function (instance) {
console.log("[ * ] Instance found in memory: " + instance)
for (var i = 1000; i < 9999; i++) {
if (instance.checkPin(i + "") == true) {
console.log("[ + ] Found correct PIN: " + i)
break
}
}
},
onComplete: function () {},
})
})

이 경우 μΈμŠ€ν„΄μŠ€κ°€ μ—†κ³  ν•¨μˆ˜κ°€ 정적이기 λ•Œλ¬Έμ— μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

정적 ν•¨μˆ˜

ν•¨μˆ˜κ°€ 정적이라면, κ·Έλƒ₯ ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€:

//hook2.js
Java.perform(function () {
console.log("[ * ] Starting PIN Brute-force, please wait...")
var PinUtil = Java.use("infosecadventures.fridademo.utils.PinUtil")

for (var i = 1000; i < 9999; i++) {
if (PinUtil.checkPin(i + "") == true) {
console.log("[ + ] Found correct PIN: " + i)
}
}
})

Hook 3 - 인수 및 λ°˜ν™˜ κ°’ κ°€μ Έμ˜€κΈ°

ν•¨μˆ˜λ₯Ό ν›„ν‚Ήν•˜μ—¬ μ „λ‹¬λœ 인수의 κ°’κ³Ό λ°˜ν™˜ κ°’μ˜ 값을 좜λ ₯ν•˜λ„λ‘ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€:

//hook3.js
Java.perform(function () {
console.log("[ * ] Starting implementation override...")

var EncryptionUtil = Java.use(
"infosecadventures.fridademo.utils.EncryptionUtil"
)
EncryptionUtil.encrypt.implementation = function (key, value) {
console.log("Key: " + key)
console.log("Value: " + value)
var encrypted_ret = this.encrypt(key, value) //Call the original function
console.log("Encrypted value: " + encrypted_ret)
return encrypted_ret
}
})

μ€‘μš”

이 νŠœν† λ¦¬μ–Όμ—μ„œλŠ” λ©”μ„œλ“œμ˜ 이름과 _.implementation_을 μ‚¬μš©ν•˜μ—¬ λ©”μ„œλ“œλ₯Ό ν›„ν‚Ήν–ˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 같은 이름을 κ°€μ§„ λ©”μ„œλ“œκ°€ μ—¬λŸ¬ 개 μžˆμ„ 경우, ν›„ν‚Ήν•˜λ €λŠ” λ©”μ„œλ“œλ₯Ό μ§€μ •ν•΄μ•Ό ν•˜λ©° 인수의 μœ ν˜•μ„ ν‘œμ‹œν•΄μ•Ό ν•©λ‹ˆλ‹€.

λ‹€μŒ νŠœν† λ¦¬μ–Όμ—μ„œ 이λ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.