pwnable.kr leg之write up
看代码:
#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=;
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[];
int r = read(fd, buf, );
write(, buf, r);
}
else{
printf("I have strong leg :P\n");
}
return ;
}
C Code
#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=;
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[];
int r = read(fd, buf, );
write(, buf, r);
}
else{
printf("I have strong leg :P\n");
}
return ;
}
分析代码,key1()+key2()+key3()==key时,得到flag
那么来分析给定的汇编代码:
(gdb) disass key1
Dump of assembler code for function key1:
0x00008cd4 <+>: push {r11} ; (str r11, [sp, #-4]!)
0x00008cd8 <+>: add r11, sp, #
0x00008cdc <+>: mov r3, pc
0x00008ce0 <+>: mov r0, r3
0x00008ce4 <+>: sub sp, r11, #
0x00008ce8 <+>: pop {r11} ; (ldr r11, [sp], #4)
0x00008cec <+>: bx lr
End of assembler dump.
返回地址是r0而r0等于pc,且为arm指令
补充知识:
PC代表程序计数器,流水线使用三个阶段,因此指令分为三个阶段执行:.取指(从存储器装载一条指令);.译码(识别将要被执行的指令);.执行(处理指令并将结果写回寄存器)。而R15
(PC)总是指向“正在取指”的指令,而不是指向“正在执行”的指令或正在“译码”的指令。一般来说,人们习惯性约定将“正在执行的指令作为参考点”,称之为当前第一条指令,因此PC总是指向第三
条指令。当ARM状态时,每条指令为4字节长,所以PC始终指向该指令地址加8字节的地址,即:PC值=当前程序执行位置+;
ARM指令是三级流水线,取指,译指,执行时同时执行的,现在PC指向的是正在取指的地址,那么cpu正在译指的指令地址是PC-(假设在ARM状态下,一个指令占4个字节),cpu正在执行的指令地
址是PC-,也就是说PC所指向的地址和现在所执行的指令地址相差8。
所以
r0的地址等于0x8cdc+0x8
再看key2:
(gdb) disass key2
Dump of assembler code for function key2:
0x00008cf0 <+>: push {r11} ; (str r11, [sp, #-4]!)
0x00008cf4 <+>: add r11, sp, #
0x00008cf8 <+>: push {r6} ; (str r6, [sp, #-4]!)
0x00008cfc <+>: add r6, pc, #
0x00008d00 <+>: bx r6
0x00008d04 <+>: mov r3, pc
0x00008d06 <+>: adds r3, #
0x00008d08 <+>: push {r3}
0x00008d0a <+>: pop {pc}
0x00008d0c <+>: pop {r6} ; (ldr r6, [sp], #4)
0x00008d10 <+>: mov r0, r3
0x00008d14 <+>: sub sp, r11, #
0x00008d18 <+>: pop {r11} ; (ldr r11, [sp], #4)
0x00008d1c <+>: bx lr
End of assembler dump.
返回地址为r3,bx r6跳转为thumb指令,所以r3=0x8d04+0x4+0x4;
附:arm与thumb跳转:
http://blog.csdn.net/itismine/article/details/4753701
再看key3:
(gdb) disass key3
Dump of assembler code for function key3:
0x00008d20 <+>: push {r11} ; (str r11, [sp, #-4]!)
0x00008d24 <+>: add r11, sp, #
0x00008d28 <+>: mov r3, lr
0x00008d2c <+>: mov r0, r3
0x00008d30 <+>: sub sp, r11, #
0x00008d34 <+>: pop {r11} ; (ldr r11, [sp], #4)
0x00008d38 <+>: bx lr
End of assembler dump.
(gdb)
返回地址为r0,r0=lr,而lr保存返回地址
返回到main函数:
(gdb) disass main
Dump of assembler code for function main:
0x00008d3c <+>: push {r4, r11, lr}
0x00008d40 <+>: add r11, sp, #
0x00008d44 <+>: sub sp, sp, #
0x00008d48 <+>: mov r3, #
0x00008d4c <+>: str r3, [r11, #-16]
0x00008d50 <+>: ldr r0, [pc, #104] ; 0x8dc0 <main+132>
0x00008d54 <+>: bl 0xfb6c <printf>
0x00008d58 <+>: sub r3, r11, #
0x00008d5c <+>: ldr r0, [pc, #96] ; 0x8dc4 <main+136>
0x00008d60 <+>: mov r1, r3
0x00008d64 <+>: bl 0xfbd8 <__isoc99_scanf>
0x00008d68 <+>: bl 0x8cd4 <key1>
0x00008d6c <+>: mov r4, r0
0x00008d70 <+>: bl 0x8cf0 <key2>
0x00008d74 <+>: mov r3, r0
0x00008d78 <+>: add r4, r4, r3
0x00008d7c <+>: bl 0x8d20 <key3>
0x00008d80 <+>: mov r3, r0
0x00008d84 <+>: add r2, r4, r3
0x00008d88 <+>: ldr r3, [r11, #-16]
0x00008d8c <+>: cmp r2, r3
0x00008d90 <+>: bne 0x8da8 <main+>
0x00008d94 <+>: ldr r0, [pc, #44] ; 0x8dc8 <main+140>
0x00008d98 <+>: bl 0x1050c <puts>
0x00008d9c <+>: ldr r0, [pc, #40] ; 0x8dcc <main+144>
0x00008da0 <+>: bl 0xf89c <system>
0x00008da4 <+>: b 0x8db0 <main+>
0x00008da8 <+>: ldr r0, [pc, #32] ; 0x8dd0 <main+148>
0x00008dac <+>: bl 0x1050c <puts>
0x00008db0 <+>: mov r3, #
0x00008db4 <+>: mov r0, r3
0x00008db8 <+>: sub sp, r11, #
0x00008dbc <+>: pop {r4, r11, pc}
0x00008dc0 <+>: andeq r10, r6, r12, lsl #
0x00008dc4 <+>: andeq r10, r6, r12, lsr #
0x00008dc8 <+>: ; <UNDEFINED> instruction: 0x0006a4b0
0x00008dcc <+>: ; <UNDEFINED> instruction: 0x0006a4bc
0x00008dd0 <+>: andeq r10, r6, r4, asr #
End of assembler dump.
第20行,key3的地址为0x8d80,
python得到key的值:
#/usr/bin/python key1=0x8cdc+0x8
key2=0x8d04+0x4+0x4
key3=0x8d80 key=key1+key2+key3 print key
得到结果:
pwnable.kr leg之write up的更多相关文章
- 【pwnable.kr】leg
pwnable从入门到放弃第八题. Download : http://pwnable.kr/bin/leg.cDownload : http://pwnable.kr/bin/leg.asm ssh ...
- pwnable.kr详细通关秘籍(二)
i春秋作家:W1ngs 原文来自:pwnable.kr详细通关秘籍(二) 0x00 input 首先看一下代码: 可以看到程序总共有五步,全部都满足了才可以得到flag,那我们就一步一步来看 这道题考 ...
- pwnable.kr的passcode
前段时间找到一个练习pwn的网站,pwnable.kr 这里记录其中的passcode的做题过程,给自己加深印象. 废话不多说了,看一下题目, 看到题目,就ssh连接进去,就看到三个文件如下 看了一下 ...
- pwnable.kr bof之write up
这一题与前两题不同,用到了静态调试工具ida 首先题中给出了源码: #include <stdio.h> #include <string.h> #include <st ...
- pwnable.kr col之write up
Daddy told me about cool MD5 hash collision today. I wanna do something like that too! ssh col@pwnab ...
- pwnable.kr brainfuck之write up
I made a simple brain-fuck language emulation program written in C. The [ ] commands are not impleme ...
- pwnable.kr login之write up
main函数如下: auth函数如下: 程序的流程如下: 输入Authenticate值,并base64解码,将解码的值代入md5_auth函数中 mad5_auth()生成其MD5值并与f87cd6 ...
- pwnable.kr simple login writeup
这道题是pwnable.kr Rookiss部分的simple login,需要我们去覆盖程序的ebp,eip,esp去改变程序的执行流程 主要逻辑是输入一个字符串,base64解码后看是否与题目 ...
- pwnable.kr第二天
3.bof 这题就是简单的数组越界覆盖,直接用gdb 调试出偏移就ok from pwn import * context.log_level='debug' payload='A'*52+p32(0 ...
随机推荐
- python 标准库 -- multiprocessing
multiprocessing 与 threading.Thread 类似 multiprocessing.Process 创建进程, 该进程可以运行用 python 编写的函数. multiproc ...
- none 和 host 网络的适用场景 - 每天5分钟玩转 Docker 容器技术(31)
本章开始讨论 Docker 网络. 我们会首先学习 Docker 提供的几种原生网络,以及如何创建自定义网络.然后探讨容器之间如何通信,以及容器与外界如何交互. Docker 网络从覆盖范围可分为单个 ...
- Spring boot 1: 使用IDEA创建Spring boot项目
项目用到的环境: Windows 10 JDK8 IntelliJ IDEA 2017.1.3 Apache Tomcat 8 Maven 3.3.3 使用IDEA新建spring boot项目 新建 ...
- 【Netty】TCP粘包和拆包
一.前言 前面已经基本上讲解完了Netty的主要内容,现在来学习Netty中的一些可能存在的问题,如TCP粘包和拆包. 二.粘包和拆包 对于TCP协议而言,当底层发送消息和接受消息时,都需要考虑TCP ...
- PHP加密字符串函数(Discuz内置的)
接触Discuz有一段时间了,一直很喜欢这个论坛程序,确实是一个很不错的程序,灰常值得我们去学习,这里介绍它其中的一个加密函数(含解密)这个加密函数的特点在于,比普通的加密函数多了一个随机密钥 ,可以 ...
- jquery元素是否可见(隐藏)
var temp1=$(".view_hidden").is(":visible");//是否可见 var temp2=$(".elem_id&quo ...
- php7 安装yar 生成docker镜像
Docker包含三个概念:(1)远程仓库即远程镜像库所有镜像的聚集地(不可进入操作).(2)本地镜像即从远程仓库拉取过来的镜像(3)运行起来的本地镜像叫做容器(分层的可操作)Docker使用:1.首先 ...
- 微信小程序开发者注册流程
一,首先打开浏览器,搜索微信公众平台 点击进入,此时还没有注册微信小程序开发账号,我们需要点击注册 进入注册页面,会出现四种账号,我们选择小程序账号 然后根据提示就可以进行注册了 注册时,需填写一下个 ...
- Ext常用开发基础知识
Ext常用开发基础知识 组件定义 //这种方法可以缓存所需要的组件 调用起来比较方便(方法一 ) Ext.define('MySecurity.view.home.HomePanel', { //添加 ...
- 关于引入多个jquery冲突的问题(附一个很好用的validate前端验证框架及使用方法)
废话不多说,进入正题: 如果一个jsp中想要使用两个不同版本的jquery怎么办呢?客官往下看: <script src="${ctxStatic}/jquery/jquery-1.8 ...