Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- joploc/jopret の目的は、x29(FPレジスタ)の値を得ること。
- E2363 26.1.B.3.109 のカーネルを例に挙げる。
- ffffffc00016e2c0 do_sync_read
- ffffffc00017cb54 sys_fcntl
- 例えば上記の時、do_sync_read + 0x6c = 0xffffffc00016e32c の辺りは、
- ffffffc00016e32c: f9401004 ldr x4, [x0,#32]
- ffffffc00016e330: 910123a0 add x0, x29, #0x48
- ffffffc00016e334: d63f0080 blr x4
- となっていて、私はここを「joploc」としてみた。
- ただ、この「形」が重要であって、この形になっていればjoplocはここじゃなくても良い。
- Cプログラムで言うと、
- fp = fcntl(dev, F_SETFL, MMAP_START);
- この命令によってカーネルのjoplocに侵入出来る。
- さて、iovyrootのソース、preparejop関数に
- addr[4] = jopret;
- とあるが、addr配列の先頭アドレスは結論から言うとjoploc侵入時点でx0レジスタに入っている。
- (厳密に言うとaddr = MMAP_STARTで、上記fcntl第3引数のMMAP_STARTがx0レジスタに入る。)
- addr配列は1個当たり64bit(8バイト)なので、
- addr[4]のアドレスはaddrの先頭 + (8バイト x 4)となる。つまり x0 + 32。
- [x0,#32]というのは、x0 + 32の中身を表すので、
- ldr x4, [x0,#32]
- これでまずx4にjopretが入る。
- add x0, x29, #0x48
- これはx29に0x48を足してx0に入れるという命令。
- blr x4
- これはx4に飛ぶよ、ということ。つまりjopretに飛ぶ。
- jopretに飛ぶとどうなるかというと、(詳しいことは分からないが)x0の値を持ったままCのプログラムに帰ってこれる。
- すなわち、先ほどの
- fp = fcntl(dev, F_SETFL, MMAP_START);
- これの「fp」にx0の値が入ってくる。
- x0にはx29 + 0x48が入ってるので、言い換えるとx0から0x48を引けば、欲しかったx29の値になる、というわけ。
- (ただ、0x48程度の誤差は最終的に無視できてしまうので、いちいち0x48を引くことはせず、そのままfpとして使ってる(^_^;)
- jopretはというと、sys_fcntl + 0x214 = 0xffffffc00017cd68 に指定しているが、この辺りは、
- ffffffc00017cd58: f9405001 ldr x1, [x0,#160]
- ffffffc00017cd5c: b4ffff61 cbz x1, 0xffffffc00017cd48
- ffffffc00017cd60: 2a1603e0 mov w0, w22
- ffffffc00017cd64: d63f0020 blr x1
- jopret
- ffffffc00017cd68: 93407c13 sxtw x19, w0
- ffffffc00017cd6c: 350012f3 cbnz w19, 0xffffffc00017cfc8
- ffffffc00017cd70: 17fffff6 b 0xffffffc00017cd48
- こんな感じになっていて、jopretはどうやらsys_fcntlのこの場所じゃないといけないらしい。
- いくつかの機種のカーネルを見てみたが、(0xffffffc0~みたいなアドレスを除いて)sys_fcntl + 0x214の辺りは必ずこの形になっていたので、
- とりあえずここをjopretにすれば良さそうだ。
Add Comment
Please, Sign In to add comment