Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust PLT stub heuristics to account for glink in PowerPC #386

Open
RyanGlScott opened this issue Jul 1, 2024 · 0 comments
Open

Adjust PLT stub heuristics to account for glink in PowerPC #386

RyanGlScott opened this issue Jul 1, 2024 · 0 comments
Labels

Comments

@RyanGlScott
Copy link
Contributor

macaw-base's PLT-stub detection machinery is currently equipped to handle x86-64 and AArch32, but not any other architectures. Recently, I found myself wanting to extend these heuristics to PowerPC. Unfortunately, the current heuristics that we use for detecting PLT stubs in macaw-base is not equipped to handle the layout of PLT stubs in PowerPC. To see what I mean, observe that if you compile the following program using a PPC32 cross compiler:

#include <stdlib.h>

int main(void) {
    int* x = malloc(sizeof(int));
    *x = 42;
    free(x);
    return 0;
}
$ ~/Software/powerpc-linux-musl-cross/bin/powerpc-linux-musl-gcc test.c -O0 -no-pie -o test.exe
$ ~/Software/powerpc-linux-musl-cross/bin/powerpc-linux-musl-objdump -DR test.exe

The objdump output will show the following:

<snip>

Disassembly of section .text:

<snip>

1000047c <main>:
1000047c:	94 21 ff e0 	stwu    r1,-32(r1)
10000480:	7c 08 02 a6 	mflr    r0
10000484:	90 01 00 24 	stw     r0,36(r1)
10000488:	93 c1 00 18 	stw     r30,24(r1)
1000048c:	93 e1 00 1c 	stw     r31,28(r1)
10000490:	7c 3f 0b 78 	mr      r31,r1
10000494:	42 9f 00 05 	bcl     20,4*cr7+so,10000498 <main+0x1c>
10000498:	7f c8 02 a6 	mflr    r30
1000049c:	3f de 00 02 	addis   r30,r30,2
100004a0:	3b de 7a 7c 	addi    r30,r30,31356
100004a4:	38 60 00 04 	li      r3,4
100004a8:	48 00 00 49 	bl      100004f0 <malloc@plt>
100004ac:	7c 69 1b 78 	mr      r9,r3
100004b0:	91 3f 00 08 	stw     r9,8(r31)
100004b4:	81 3f 00 08 	lwz     r9,8(r31)
100004b8:	39 40 00 2a 	li      r10,42
100004bc:	91 49 00 00 	stw     r10,0(r9)
100004c0:	80 7f 00 08 	lwz     r3,8(r31)
100004c4:	48 00 00 6d 	bl      10000530 <free@plt>
100004c8:	39 20 00 00 	li      r9,0
100004cc:	7d 23 4b 78 	mr      r3,r9
100004d0:	39 7f 00 20 	addi    r11,r31,32
100004d4:	80 0b 00 04 	lwz     r0,4(r11)
100004d8:	7c 08 03 a6 	mtlr    r0
100004dc:	83 cb ff f8 	lwz     r30,-8(r11)
100004e0:	83 eb ff fc 	lwz     r31,-4(r11)
100004e4:	7d 61 5b 78 	mr      r1,r11
100004e8:	4e 80 00 20 	blr
100004ec:	60 00 00 00 	nop

100004f0 <malloc@plt>:
100004f0:	3d 60 10 02 	lis     r11,4098
100004f4:	81 6b 00 00 	lwz     r11,0(r11)
100004f8:	7d 69 03 a6 	mtctr   r11
100004fc:	4e 80 04 20 	bctr

10000500 <__deregister_frame_info@plt>:
10000500:	3d 60 10 02 	lis     r11,4098
10000504:	81 6b 00 04 	lwz     r11,4(r11)
10000508:	7d 69 03 a6 	mtctr   r11
1000050c:	4e 80 04 20 	bctr

10000510 <__libc_start_main@plt>:
10000510:	3d 60 10 02 	lis     r11,4098
10000514:	81 6b 00 08 	lwz     r11,8(r11)
10000518:	7d 69 03 a6 	mtctr   r11
1000051c:	4e 80 04 20 	bctr

10000520 <__register_frame_info@plt>:
10000520:	3d 60 10 02 	lis     r11,4098
10000524:	81 6b 00 0c 	lwz     r11,12(r11)
10000528:	7d 69 03 a6 	mtctr   r11
1000052c:	4e 80 04 20 	bctr

10000530 <free@plt>:
10000530:	3d 60 10 02 	lis     r11,4098
10000534:	81 6b 00 10 	lwz     r11,16(r11)
10000538:	7d 69 03 a6 	mtctr   r11
1000053c:	4e 80 04 20 	bctr

10000540 <__glink>:
10000540:	60 00 00 00 	nop
10000544:	60 00 00 00 	nop
10000548:	60 00 00 00 	nop
1000054c:	60 00 00 00 	nop

10000550 <__glink_PLTresolve>:
10000550:	3d 80 10 02 	lis     r12,4098
10000554:	3d 6b f0 00 	addis   r11,r11,-4096
10000558:	80 0c ff f8 	lwz     r0,-8(r12)
1000055c:	39 6b fa c0 	addi    r11,r11,-1344
10000560:	7c 09 03 a6 	mtctr   r0
10000564:	7c 0b 5a 14 	add     r0,r11,r11
10000568:	81 8c ff fc 	lwz     r12,-4(r12)
1000056c:	7d 60 5a 14 	add     r11,r0,r11
10000570:	4e 80 04 20 	bctr
10000574:	60 00 00 00 	nop
10000578:	60 00 00 00 	nop
1000057c:	60 00 00 00 	nop
10000580:	60 00 00 00 	nop
10000584:	60 00 00 00 	nop
10000588:	60 00 00 00 	nop
1000058c:	60 00 00 00 	nop

<snip>

Disassembly of section .plt:

10020000 <.plt>:
10020000:	10 00 05 40 	vsubcuq v0,v0,v0
			10020000: R_PPC_JMP_SLOT	malloc
10020004:	10 00 05 44 	vorc    v0,v0,v0
			10020004: R_PPC_JMP_SLOT	__deregister_frame_info
10020008:	10 00 05 48 	vncipher v0,v0,v0
			10020008: R_PPC_JMP_SLOT	__libc_start_main
1002000c:	10 00 05 4c 	vbpermq v0,v0,v0
			1002000c: R_PPC_JMP_SLOT	__register_frame_info
10020010:	10 00 05 50 	.long 0x10000550
			10020010: R_PPC_JMP_SLOT	free

This looks quite different from how PLT stubs work on x86-64 and AArch32. Unlike on those architectures, on PowerPC we see that the main function invokes PLT stubs that are located in the .text section rather than the .plt section. This is bad news for macaw's current heuristics, which always assume that PLT stubs are located in a .plt or .plt.got section. What's more, there is a .plt section, but it contains the addresses of PLT entries (which refer to a special __glink function) rather than the PLT stubs themselves. In this sense, the .plt section on PowerPC behaves more like the .got/.got.plt section on other architectures. (This blog post explains the nuances better than I can.)

As such, macaw's heuristics will return incorrect PLT stub addresses when used on a PowerPC binary. It is likely possible to generalize the heuristics to make it work over PowerPC, but we may need to revisit some assumptions that we currently make about what things live where.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant