跳转某个地址执行

最近看指针,发现有个奇淫方法,直接跳转执行某个地址执行程序。

例如:要跳转0x1000地址执行代码,代码是 ((void)(*)(void))0x1000)()

注意:以下测试方法在esp32单片机上执行,在linux上,由于每个应用都是虚拟内存,所以无法通过地址跳转执行某段程序。

为什么会这样子可以直接跳转到某个地址执行程序呢?首先先看一个demo。

void print(void){
    printf("this is a test\r\n");
}
void app_main(void)
{
    printf("Hello world!\n");

    /* Print chip information */
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU core(s), WiFi%s%s, ",
            CONFIG_IDF_TARGET,
            chip_info.cores,
            (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
            (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
    void (*function_p)(void);
    function_p=print;
     printf("The address of function = %d !\n", (int )function_p);
     vTaskDelay(100);
     printf("here\r\n");
     ((void (*)(void))1074602104)();
     (*function_p)();
    // printf("print=%p\r\n",function_p);
}

以上执行结果是

Hello world!
This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, The address of function = 1074602104 !
here
this is a test
this is a test

由以上代码可知,

该行代码 function_p=print; 是把print函数首地址传递给function_p指针。

function_p指针指向地址是1074602104,即也是print函数首地址。

然后看这一句代码((void (*)(void))1074602104)();

void (*)(void)是函数指针,((void (*)(void))1074602104意思是把1074602104转成函数指针,那么程序可以调准到0x1074602104

一般采用高级语言编程后者写纯软件时不会遇到让程序绝对跳转执行,但是涉及到底层开发时候,会用到该方式,比如STM32 IAP在线程序升级过程中,在写bootloader程序时就要让程序跳到绝对地址。

指定地址读写入值

想在某一个地址读写数据,发放实现如下

方法一:

int *p;
p=(int *)0x10000;
*p=1234;

该方法时把p指向0x10000地址,然后给p赋值1234

方法二:

*(int *)0x10000=1234

同样该方法直接向0x10000地址赋值1234.

请看以下demo

/* Hello World Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"

void app_main(void)
{
    printf("Hello world!\n");

    /* Print chip information */
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU cores, WiFi%s%s, ",
            CONFIG_IDF_TARGET,
            chip_info.cores,
            (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
            (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    printf("silicon revision %d, ", chip_info.revision);

    int i=0;
    printf("address=%p\r\n",&i);
    float *p;
    p=(float *)0x3ffb468e;
    (*p)=1245;
    printf("value=%f\r\n",(*p));
/*********second************************/
    *(int *)0x3ffb479f=12345;
    printf("value=%d\r\n",*(int *)0x3ffb479f);

}

运行结果如下

Hello world!
This is esp32 chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 1, address=0x3ffb467c
value=1245.000000
value=12345

注意:并不是所有地址都合法的,我这里想读取变量i的地址,i的地址前后一般都可以读写。

一般编程用不了该方法,但是在单片机对外设进行读写操作时候可能会用到。

Logo

更多推荐