Challenge Description
We get the following hint:
Daddy told me I should study ARM architecture.
But I know Intel architecture and it should be similar.
Why bother to study ARM?
Download : http://pwnable.kr/bin/leg.c
Download : http://pwnable.kr/bin/leg.asm
ssh leg@pwnable.kr -p2222 (pw:guest)
Connect using:
ssh leg@pwnable.kr -p2222
We get a BusyBox machine with the following information:
/ $ uname -a
Linux (none) 3.11.4 #5 Sat Oct 12 00:15:00 EDT 2013 armv5tejl GNU/Linux
/ $ ls
bin dev flag linuxrc root sys
boot etc leg proc sbin usr
/ $ whoami
busy
We are given the source code for leg, along with its disassembly.
Source Code Analysis
#include <stdio.h>
#include <fcntl.h>
int key1(){
asm("mov r3, pc\n");
}
int key2(){
asm(
"push {r6}\n"
"add r6, pc, $1\n"
"bx r6\n"
".code 16\n"
"mov r3, pc\n"
"add r3, $0x4\n"
"push {r3}\n"
"pop {pc}\n"
".code 32\n"
"pop {r6}\n"
);
}
int key3(){
asm("mov r3, lr\n");
}
int main(){
int key=0;
printf("Daddy has very strong arm! : ");
scanf("%d", &key);
if( (key1()+key2()+key3()) == key ){
printf("Congratz!\n");
int fd = open("flag", O_RDONLY);
char buf[100];
int r = read(fd, buf, 100);
write(0, buf, r);
}
else{
printf("I have strong leg :P\n");
}
return 0;
}
The goal is to determine the return values of key1, key2, and key3, and provide their sum as input.
General ARM notes
On ARM, the return value of a function is stored in the r0 register. Therefore, for each function we need to track what value ends up in r0.
Analyzing key1()
Disassembly:
...
0x00008cdc <+8>: mov r3, pc
0x00008ce0 <+12>: mov r0, r3
...
Here, r0 = r3, and r3 is set to the value of pc. In ARM state, pc is the current instruction address + 8.
The mov r3, pc instruction is at 0x00008cdc, so:
pc = 0x00008cdc + 8 = 0x00008ce4
Therefore, key1() = 0x00008ce4.
Analyzing key2()
Relevant instructions:
...
0x00008d04 <+20>: mov r3, pc
0x00008d06 <+22>: adds r3, #4
0x00008d10 <+32>: mov r0, r3
This part runs in Thumb mode, which we can see because the instruction at
0x00008d06 is at 0x00008d04 + 2, indicating 16-bit instructions.
In Thumb mode, pc is the current instruction address + 4.
So:
pc = 0x00008d04 + 4 = 0x00008d08
r3 = 0x00008d08 + 4 = 0x00008d0c
Thus key2() = 0x00008d0c.
Analyzing key3()
Disassembly:
0x00008d28 <+8>: mov r3, lr
0x00008d2c <+12>: mov r0, r3
Here, r0 = r3, and r3 is loaded from lr. On ARM, lr contains the return address of the function.
From main, the call to key3 returns to:
0x00008d80 <+68>: mov r3, r0
So key3() = 0x00008d80.
Solution
Adding it all together:
0x00008ce4
+0x00008d0c
+0x00008d80
------------
0x0001a770 = 108400
Let's try:
/ $ ./leg
Daddy has very strong arm! : 108400
Congratz!
daddy_has_lot_of_ARM_muscl3
Success! 🎉