python字节码详解,bytecode手动反编译。

前言

本文主要是介绍如何根据Bytecode手撸得到py源码,这是一种ctf常见题目。关于Bytecode的实现过程,和虚拟机之间的关系可以自行深入学习(我在写的时候查阅资料发现本站上面大部分文章都是将这一部分的,所以就不过多赘述啦(其实是我也不太会hhh))可能也是手撸其实比较基础吧,新手看看就好( ˝ᗢ̈˝ )

简介

字节码(Bytecode):通常指的是已经经过编译,但与特定机器代码无关,需要解释器转译后才能成为机器代码的中间代码。字节码通常不像源码一样可以让人阅读,而是编码后的数值常量、引用、指令(也称操作码,Operation Code)等构成的序列。

拿 Python 说明,Python 解释器先翻译 Python 源代码( .py 文件)为 Python 字节码( .pyc 文件),然后再由 Python 虚拟机来执行 Python 字节码。Python 字节码是一种类似于汇编指令的中间语言,一条 Python 语句会对应若干条字节码指令,虚拟机一条条执行字节码指令,将其翻译成机器代码,并交个 CPU 执行,从而完成程序的执行。

dis模块--python反汇编神器

 

dis模块是 Python 的标准库之一,用于反汇编 Python 字节码。它允许你查看 Python 函数或模块的字节码指令,这对于理解 Python 代码的底层运行方式和性能优化非常有帮助。

可以使用 dis 模块来查看函数、方法或模块中的字节码指令。以下是一个基本示例:

import dis

def example_function(x, y):
    result = x + y
    return result

dis.dis(example_function)

输出:

d2a901d39ed34fe3b18cd2ac1d7991ed.png

在这个示例中,我们导入 dis 模块,定义了一个名为 example_function 的函数,然后使用 dis.dis() 函数来查看该函数的字节码指令。

dis.dis() 输出的结果将显示函数中的每个字节码指令以及相关的信息,如字节码的偏移量、操作码、操作数等。

dis还有更多的用法,可以参考:

dis --- Python 字节码反汇编器 — Python 3.12.0 文档

变量

比较常见的几种类型

  1. LOAD_CONST: 用于加载常量。
  2. STORE_FAST: 用于将值存储到本地变量
import dis

def example_function(x, y):
    x = 42  # x是整数
    x = "Hello, World!"  # x是字符串
    n = n / p
dis.dis(example_function)

51ed7f052c5b4629a0f9629fea094367.png

3.LOAD_FAST一般加载局部变量的值,也就是读取值,用于计算或者函数调用传参等。

4.LOAD_GLOBAL用来加载全局变量,包括指定函数名,类名,模块名等全局符号。

5.STORE_GLOBAL用来给全局变量赋值。

 

import dis

def text():
    global global1
    global1 = 101
    print(global1)

dis.dis(text)

800539c6577b448192198a30f3fd411a.png

常用数据类型

1.list

在 Python 字节码中,列表(List)是一种常见的数据结构,用于存储有序的数据元素。

BUILD_LIST: 这个字节码操作用于构建一个列表对象。它接受一个整数参数,表示要构建的列表中元素的数量。后面的操作码会将元素依次添加到列表中。

LIST_APPEND: 当要向列表添加元素时,这个字节码操作会从堆栈中弹出一个值,并将其添加到列表中。这通常与循环结构一起使用,以将多个值添加到列表。

BINARY_SUBSCR: 当你需要获取列表中特定索引的元素时,这个操作码会获取列表和索引值,然后返回列表中对应索引的元素

示例代码:

import dis

def example_function(x, y):
    my_list = [1, 2, 3, 4]
    my_list.append(5)
    element = my_list[2]
dis.dis(example_function)

输出:

1f374a5b0dcf49cb9248c8a786139d31.png

在上述示例中,BUILD_LIST 指令用于构建列表,LOAD_FAST 用于加载变量 my_listLIST_APPEND 用于将元素添加到列表中,BINARY_SUBSCR 用于获取列表中的元素

 

2.dict

字典(Dictionary)是一种常见的数据结构,用于存储键-值对。

BUILD_MAP用于创建一个空的dict。STORE_MAP用于初始化dict的内容。

示例:

import dis

def example_function(x, y):
    my_dict = {"name": "Alice", "age": 30, "city": "New York"}
    my_dict["occupation"] = "Engineer"
    occupation = my_dict["occupation"]

dis.dis(example_function)

 输出:

29a8a01e3bef4b41883664c4eeac8d29.png

 

3.slice

切片(Slice)是一种用于访问可迭代对象(如列表、字符串、元组等)的子集的方法。切片操作不会创建新的列表或字符串,而是返回原始对象的一个子集。

BUILD_SLICE用于创建slice。对于list、元组、字符串都可以使用slice的方式进行访问

SLICE+0, SLICE+1, SLICE+2, SLICE+3: 这些字节码操作用于执行不同类型的切片操作。

例如,SLICE+2 用于执行 a[start:stop] 形式的切片,其中 startstop 由堆栈上的值提供。SLICE+1 用于执行 a[start:] 形式的切片,其中 start 由堆栈上的值提供。SLICE+0 用于执行 a[:] 形式的切片,返回原始对象的一个拷贝。

 

STORE_SLICE+0, STORE_SLICE+1, STORE_SLICE+2, STORE_SLICE+3: 这些字节码操作用于将切片的结果存储回原始对象。

例如,STORE_SLICE+2 用于执行 a[start:stop] = b 形式的切片赋值,其中 startstop 由堆栈上的值提供,而 b 是要赋值的对象。

 

DELETE_SLICE+0, DELETE_SLICE+1, DELETE_SLICE+2, DELETE_SLICE+3: 这些字节码操作用于删除切片的元素。

例如,DELETE_SLICE+1 用于执行 del a[start:] 形式的切片删除,其中 start 由堆栈上的值提供。

这里应该不太好理解。最好还是自己多写写,用dis反汇编看看观察一下特征。

代码示例:

import dis

def example_function(x, y):
    my_list = [1, 2, 3, 4, 5]
    sub_list = my_list[1:4]
    my_list[2:4] = [6, 7]
    del my_list[1:3]

dis.dis(example_function)

输出:

1ff88596b35843cbadc062423db5a7de.png

 

循环

SETUP_LOOP用于开始一个循环。SETUP_LOOP 26 (to 35)35表示循环退出点。

1.while

先看一下例子再分析:

示例程序:
 

import dis

def example_function(x, y):
    total = 0
    count = 1
    while count <= 5:
        total += count
        count += 1
dis.dis(example_function)

输出:

ea191c62c0ac44ae903d0ef35a0f7757.png

在上述示例中,SETUP_LOOP 用于设置循环块,POP_JUMP_IF_FALSE 用于在条件不满足时跳出循环。循环体中的操作用于计算变量 total 的值,并在每次迭代中递增 count,直到 count 不再小于等于5为止。

so.

 

  1. SETUP_LOOP用于开始一个循环。SETUP_LOOP 26 (to 35)35表示循环退出点

  2. POP_BLOCK: 用于弹出循环块的指令,通常在循环的末尾使用。

  3. BREAK_LOOP: 用于中断当前循环的执行。

  4. CONTINUE_LOOP: 用于跳回循环开始的指令,以实现循循环的迭代。

  5. POP_JUMP_IF_FALSE: 用于在条件不满足时跳转到指定位置

  6.  

    COMPARE_OP: 用于执行比较操作,例如,检查是否满足循环条件。

     

 

2. for in 

  1. FOR_ITER: 这个字节码操作用于迭代可迭代对象(如列表、元组等)的元素。它通常与 FOR_LOOP 指令一起使用,用于执行 for 循环。

  2. FOR_LOOP: 这个字节码操作用于定义一个 for 循环的循环体。它接受一个循环控制变量,该变量用于迭代可迭代对象中的元素。

示例:

import dis

def example_function(x, y):
    my_list = [1, 2, 3, 4, 5]
    total = 0
    for item in my_list:
        total += item
dis.dis(example_function)

反汇编结果:

6093d6cb79ea4bf696fd44e3ac84dca5.png

 

if判断

POP_JUMP_IF_FALSEJUMP_FORWARD一般用于分支判断跳转。

POP_JUMP_IF_FALSE表示条件结果为FALSE就跳转到目标偏移指令。

JUMP_FORWARD直接跳转到目标偏移指令。

示例:
 

import dis

def example_function(x, y):
    x = 10
    if x < 5:
        result = "x is less than 5"
    else:
        result = "x is not less than 5"

dis.dis(example_function)

反汇编结果:
 

71c66ae7bfc641dcbca35471589adefa.png

  COMPARE_OP 用于比较 x5POP_JUMP_IF_FALSE 用于根据条件跳转到不同的代码块。条件语句根据 x 的值设置变量 result 的不同值。

其他指令

可以详见官方文档

 

实战手撸反编译过程

[羊城杯2022]Bytecode

 4           0 LOAD_CONST               0 (3)
              3 LOAD_CONST               1 (37)
              6 LOAD_CONST               2 (72)
              9 LOAD_CONST               3 (9)
             12 LOAD_CONST               4 (6)
             15 LOAD_CONST               5 (132)
             18 BUILD_LIST               6
             21 STORE_NAME               0 (en)

  5          24 LOAD_CONST               6 (101)
             27 LOAD_CONST               7 (96)
             30 LOAD_CONST               8 (23)
             33 LOAD_CONST               9 (68)
             36 LOAD_CONST              10 (112)
             39 LOAD_CONST              11 (42)
             42 LOAD_CONST              12 (107)
             45 LOAD_CONST              13 (62)
             48 LOAD_CONST               7 (96)
             51 LOAD_CONST              14 (53)
             54 LOAD_CONST              15 (176)
             57 LOAD_CONST              16 (179)
             60 LOAD_CONST              17 (98)
             63 LOAD_CONST              14 (53)
             66 LOAD_CONST              18 (67)
             69 LOAD_CONST              19 (29)
             72 LOAD_CONST              20 (41)
             75 LOAD_CONST              21 (120)
             78 LOAD_CONST              22 (60)
             81 LOAD_CONST              23 (106)
             84 LOAD_CONST              24 (51)
             87 LOAD_CONST               6 (101)
             90 LOAD_CONST              25 (178)
             93 LOAD_CONST              26 (189)
             96 LOAD_CONST               6 (101)
             99 LOAD_CONST              27 (48)
            102 BUILD_LIST              26
            105 STORE_NAME               1 (output)

  7         108 LOAD_CONST              28 ('welcome to GWHT2020')
            111 PRINT_ITEM          
            112 PRINT_NEWLINE       

  9         113 LOAD_NAME                2 (raw_input)
            116 LOAD_CONST              29 ('please input your flag:')
            119 CALL_FUNCTION            1
            122 STORE_NAME               3 (flag)

 10         125 LOAD_NAME                3 (flag)
            128 STORE_NAME               4 (str)

 12         131 LOAD_NAME                5 (len)
            134 LOAD_NAME                4 (str)
            137 CALL_FUNCTION            1
            140 STORE_NAME               6 (a)

 13         143 LOAD_NAME                6 (a)
            146 LOAD_CONST              30 (38)
            149 COMPARE_OP               0 (<)
            152 POP_JUMP_IF_FALSE      173

 14         155 LOAD_CONST              31 ('lenth wrong!')
            158 PRINT_ITEM          
            159 PRINT_NEWLINE       

 15         160 LOAD_NAME                7 (exit)
            163 LOAD_CONST              32 (0)
            166 CALL_FUNCTION            1
            169 POP_TOP             
            170 JUMP_FORWARD             0 (to 173)

 17     >>  173 LOAD_NAME                8 (ord)
            176 LOAD_NAME                4 (str)
            179 LOAD_CONST              32 (0)
            182 BINARY_SUBSCR       
            183 CALL_FUNCTION            1
            186 LOAD_CONST              33 (2020)
            189 BINARY_MULTIPLY     
            190 LOAD_NAME                8 (ord)
            193 LOAD_NAME                4 (str)
            196 LOAD_CONST              34 (1)
            199 BINARY_SUBSCR       
            200 CALL_FUNCTION            1
            203 BINARY_ADD          
            204 LOAD_CONST              33 (2020)
            207 BINARY_MULTIPLY     
            208 LOAD_NAME                8 (ord)
            211 LOAD_NAME                4 (str)
            214 LOAD_CONST              35 (2)
            217 BINARY_SUBSCR       
            218 CALL_FUNCTION            1
            221 BINARY_ADD          
            222 LOAD_CONST              33 (2020)
            225 BINARY_MULTIPLY     
            226 LOAD_NAME                8 (ord)
            229 LOAD_NAME                4 (str)
            232 LOAD_CONST               0 (3)
            235 BINARY_SUBSCR       
            236 CALL_FUNCTION            1
            239 BINARY_ADD          
            240 LOAD_CONST              33 (2020)
            243 BINARY_MULTIPLY     
            244 LOAD_NAME                8 (ord)
            247 LOAD_NAME                4 (str)
            250 LOAD_CONST              36 (4)
            253 BINARY_SUBSCR       
            254 CALL_FUNCTION            1
            257 BINARY_ADD          
            258 LOAD_CONST              37 (1182843538814603)
            261 COMPARE_OP               2 (==)
            264 POP_JUMP_IF_FALSE      275

 18         267 LOAD_CONST              38 ('good!continue\xe2\x80\xa6\xe2\x80\xa6')
            270 PRINT_ITEM          
            271 PRINT_NEWLINE       
            272 JUMP_FORWARD            15 (to 290)

 20     >>  275 LOAD_CONST              39 ('bye~')
            278 PRINT_ITEM          
            279 PRINT_NEWLINE       

 21         280 LOAD_NAME                7 (exit)
            283 LOAD_CONST              32 (0)
            286 CALL_FUNCTION            1
            289 POP_TOP             

 23     >>  290 BUILD_LIST               0
            293 STORE_NAME               9 (x)

 24         296 LOAD_CONST              40 (5)
            299 STORE_NAME              10 (k)

 25         302 SETUP_LOOP             128 (to 433)
            305 LOAD_NAME               11 (range)
            308 LOAD_CONST              41 (13)
            311 CALL_FUNCTION            1
            314 GET_ITER            
        >>  315 FOR_ITER               114 (to 432)
            318 STORE_NAME              12 (i)

 26         321 LOAD_NAME                8 (ord)
            324 LOAD_NAME                4 (str)
            327 LOAD_NAME               10 (k)
            330 BINARY_SUBSCR       
            331 CALL_FUNCTION            1
            334 STORE_NAME              13 (b)

 27         337 LOAD_NAME                8 (ord)
            340 LOAD_NAME                4 (str)
            343 LOAD_NAME               10 (k)
            346 LOAD_CONST              34 (1)
            349 BINARY_ADD          
            350 BINARY_SUBSCR       
            351 CALL_FUNCTION            1
            354 STORE_NAME              14 (c)

 28         357 LOAD_NAME               14 (c)
            360 LOAD_NAME                0 (en)
            363 LOAD_NAME               12 (i)
            366 LOAD_CONST               4 (6)
            369 BINARY_MODULO       
            370 BINARY_SUBSCR       
            371 BINARY_XOR          
            372 STORE_NAME              15 (a11)

 29         375 LOAD_NAME               13 (b)
            378 LOAD_NAME                0 (en)
            381 LOAD_NAME               12 (i)
            384 LOAD_CONST               4 (6)
            387 BINARY_MODULO       
            388 BINARY_SUBSCR       
            389 BINARY_XOR          
            390 STORE_NAME              16 (a22)

 30         393 LOAD_NAME                9 (x)
            396 LOAD_ATTR               17 (append)
            399 LOAD_NAME               15 (a11)
            402 CALL_FUNCTION            1
            405 POP_TOP             

 31         406 LOAD_NAME                9 (x)
            409 LOAD_ATTR               17 (append)
            412 LOAD_NAME               16 (a22)
            415 CALL_FUNCTION            1
            418 POP_TOP             

 32         419 LOAD_NAME               10 (k)
            422 LOAD_CONST              35 (2)
            425 INPLACE_ADD         
            426 STORE_NAME              10 (k)
            429 JUMP_ABSOLUTE          315
        >>  432 POP_BLOCK           

 33     >>  433 LOAD_NAME                9 (x)
            436 LOAD_NAME                1 (output)
            439 COMPARE_OP               2 (==)
            442 POP_JUMP_IF_FALSE      453

 34         445 LOAD_CONST              38 ('good!continue\xe2\x80\xa6\xe2\x80\xa6')
            448 PRINT_ITEM          
            449 PRINT_NEWLINE       
            450 JUMP_FORWARD            15 (to 468)

 36     >>  453 LOAD_CONST              42 ('oh,you are wrong!')
            456 PRINT_ITEM          
            457 PRINT_NEWLINE       

 37         458 LOAD_NAME                7 (exit)
            461 LOAD_CONST              32 (0)
            464 CALL_FUNCTION            1
            467 POP_TOP             

 39     >>  468 LOAD_NAME                5 (len)
            471 LOAD_NAME                4 (str)
            474 CALL_FUNCTION            1
            477 STORE_NAME              18 (l)

 40         480 LOAD_NAME                8 (ord)
            483 LOAD_NAME                4 (str)
            486 LOAD_NAME               18 (l)
            489 LOAD_CONST              43 (7)
            492 BINARY_SUBTRACT     
            493 BINARY_SUBSCR       
            494 CALL_FUNCTION            1
            497 STORE_NAME              19 (a1)

 41         500 LOAD_NAME                8 (ord)
            503 LOAD_NAME                4 (str)
            506 LOAD_NAME               18 (l)
            509 LOAD_CONST               4 (6)
            512 BINARY_SUBTRACT     
            513 BINARY_SUBSCR       
            514 CALL_FUNCTION            1
            517 STORE_NAME              20 (a2)

 42         520 LOAD_NAME                8 (ord)
            523 LOAD_NAME                4 (str)
            526 LOAD_NAME               18 (l)
            529 LOAD_CONST              40 (5)
            532 BINARY_SUBTRACT     
            533 BINARY_SUBSCR       
            534 CALL_FUNCTION            1
            537 STORE_NAME              21 (a3)

 43         540 LOAD_NAME                8 (ord)
            543 LOAD_NAME                4 (str)
            546 LOAD_NAME               18 (l)
            549 LOAD_CONST              36 (4)
            552 BINARY_SUBTRACT     
            553 BINARY_SUBSCR       
            554 CALL_FUNCTION            1
            557 STORE_NAME              22 (a4)

 44         560 LOAD_NAME                8 (ord)
            563 LOAD_NAME                4 (str)
            566 LOAD_NAME               18 (l)
            569 LOAD_CONST               0 (3)
            572 BINARY_SUBTRACT     
            573 BINARY_SUBSCR       
            574 CALL_FUNCTION            1
            577 STORE_NAME              23 (a5)

 45         580 LOAD_NAME                8 (ord)
            583 LOAD_NAME                4 (str)
            586 LOAD_NAME               18 (l)
            589 LOAD_CONST              35 (2)
            592 BINARY_SUBTRACT     
            593 BINARY_SUBSCR       
            594 CALL_FUNCTION            1
            597 STORE_NAME              24 (a6)

 46         600 LOAD_NAME               19 (a1)
            603 LOAD_CONST               0 (3)
            606 BINARY_MULTIPLY     
            607 LOAD_NAME               20 (a2)
            610 LOAD_CONST              35 (2)
            613 BINARY_MULTIPLY     
            614 BINARY_ADD          
            615 LOAD_NAME               21 (a3)
            618 LOAD_CONST              40 (5)
            621 BINARY_MULTIPLY     
            622 BINARY_ADD          
            623 LOAD_CONST              44 (1003)
            626 COMPARE_OP               2 (==)
            629 POP_JUMP_IF_FALSE      807

 47         632 LOAD_NAME               19 (a1)
            635 LOAD_CONST              36 (4)
            638 BINARY_MULTIPLY     
            639 LOAD_NAME               20 (a2)
            642 LOAD_CONST              43 (7)
            645 BINARY_MULTIPLY     
            646 BINARY_ADD          
            647 LOAD_NAME               21 (a3)
            650 LOAD_CONST               3 (9)
            653 BINARY_MULTIPLY     
            654 BINARY_ADD          
            655 LOAD_CONST              45 (2013)
            658 COMPARE_OP               2 (==)
            661 POP_JUMP_IF_FALSE      807

 48         664 LOAD_NAME               19 (a1)
            667 LOAD_NAME               20 (a2)
            670 LOAD_CONST              46 (8)
            673 BINARY_MULTIPLY     
            674 BINARY_ADD          
            675 LOAD_NAME               21 (a3)
            678 LOAD_CONST              35 (2)
            681 BINARY_MULTIPLY     
            682 BINARY_ADD          
            683 LOAD_CONST              47 (1109)
            686 COMPARE_OP               2 (==)
            689 POP_JUMP_IF_FALSE      804

 49         692 LOAD_NAME               22 (a4)
            695 LOAD_CONST               0 (3)
            698 BINARY_MULTIPLY     
            699 LOAD_NAME               23 (a5)
            702 LOAD_CONST              35 (2)
            705 BINARY_MULTIPLY     
            706 BINARY_ADD          
            707 LOAD_NAME               24 (a6)
            710 LOAD_CONST              40 (5)
            713 BINARY_MULTIPLY     
            714 BINARY_ADD          
            715 LOAD_CONST              48 (671)
            718 COMPARE_OP               2 (==)
            721 POP_JUMP_IF_FALSE      801

 50         724 LOAD_NAME               22 (a4)
            727 LOAD_CONST              36 (4)
            730 BINARY_MULTIPLY     
            731 LOAD_NAME               23 (a5)
            734 LOAD_CONST              43 (7)
            737 BINARY_MULTIPLY     
            738 BINARY_ADD          
            739 LOAD_NAME               24 (a6)
            742 LOAD_CONST               3 (9)
            745 BINARY_MULTIPLY     
            746 BINARY_ADD          
            747 LOAD_CONST              49 (1252)
            750 COMPARE_OP               2 (==)
            753 POP_JUMP_IF_FALSE      798

 51         756 LOAD_NAME               22 (a4)
            759 LOAD_NAME               23 (a5)
            762 LOAD_CONST              46 (8)
            765 BINARY_MULTIPLY     
            766 BINARY_ADD          
            767 LOAD_NAME               24 (a6)
            770 LOAD_CONST              35 (2)
            773 BINARY_MULTIPLY     
            774 BINARY_ADD          
            775 LOAD_CONST              50 (644)
            778 COMPARE_OP               2 (==)
            781 POP_JUMP_IF_FALSE      795

 52         784 LOAD_CONST              51 ('congraduation!you get the right flag!')
            787 PRINT_ITEM          
            788 PRINT_NEWLINE       
            789 JUMP_ABSOLUTE          795
            792 JUMP_ABSOLUTE          798
        >>  795 JUMP_ABSOLUTE          801
        >>  798 JUMP_ABSOLUTE          804
        >>  801 JUMP_ABSOLUTE          807
        >>  804 JUMP_FORWARD             0 (to 807)
        >>  807 LOAD_CONST              52 (None)
            810 RETURN_VALUE 

有点长,不太好看;可以下载附件自己看;

接下来就是一步一步手撸出源代码,手撸的过程中我有些地方不理解的,就用dis反汇编查看一下,是否和txt中内容相似,介绍一下dis的第二种反汇编方式,在终端中输入:
 

python -m dis wenjianming.py




en = [3,31,72,9,6,132]
output = [101,96,23,68,112,42,107,62,96,53,176,179,98,53,67,29,41,120,60,106,51,101,178,189,101,48]
print('welcome to GWHT2020')


flag = input('please input your flag:')
str = flag

a = len(str)
if a < 38:
    print('lenth wrong!')
    exit(0)

if (ord((str[0] * 2020) + (ord(str[1]) * 2020) + (ord(str[2]) * 2020) + (ord(str[3]) * 2020) + (ord(str[4])))== 1182843538814603) :
    print('good!continue\xe2\x80\xa6\xe2\x80\xa6')
else:
    print('bye~')
    exit(0)

x = []
k = 5
for i in range(13):
    b = ord(str[k])
    c = ord(str[k + 1])
    a11 = c ^ en[i % 6]
    a22 = b ^ en[i % 6]
    x.append(a11)
    x.append(a22)
    k = k + 2
if x == output:
    print('good!continue\xe2\x80\xa6\xe2\x80\xa6')
else:
    print('oh,you are wrong!')
    exit(0)

l = len(str)
a1 = ord(str[l - 7])
a2 = ord(str[l - 6])
a3 = ord(str[l - 5])
a4 = ord(str[l - 4])
a5 = ord(str[l - 3])
a6 = ord(str[l - 2])
if a1 * 3 + a2 * 2 + a3 * 5 == 1003:
    if a1 *4 + a2 * 7 + a3 * 9 == 2013:
        if a1 * 8 + a2 * 8 + a3 * 2 == 1109:
            if a4 * 3 + a5 * 2 + a6 * 5 == 671:
                if a4 * 4 + a5 * 7 + a6 * 9 == 1252:
                    if a4 * 8 + a5 * 8 + a6 * 2 == 644:
                        print("congraduation!you get the right flag!")

 

手撸的时候注意Python字节码是一种栈方式存储的,则可以翻译得比较快

例如下面这个代码就是将 ord,str,l,7依次入栈

       # 调用BINARY_SUBTRACT则变成 l - 7
       # 调用BINARY_SUBSCR则变成 str[l-7]
       # 调用CALL_FUNCTION则变成 ord(str[l-7])
       # 调用STORE_NAME则变成 a1 = ord(str[l-7])

;目前类似题目如果给的是 txt文件,应该都只能手动反编译出来,我没有找到什么可以一键反编译的。如果是pyc是文件的话,就可以用uncompyle6或者在线网站进行反编译。

这里反编译出来后,就比较简单了,三个地方分别加密。写个exp慢慢看:
 

#第一部分
前五个字符也可以用z3求,步过猜都可以猜出来是GWHT{

# 第二部分
#俩个字符异或一次
en = [3,37,72,9,6,132]
output = [101,96,23,68,112,42,107,62,96,53,176,179,98,53,67,29,41,120,60,106,51,101,178,189,101,48]
flag=''
k=0
for i in range(13):
	flag+=chr(output[k+1]^en[i%6])
	flag+=chr(output[k]^en[i%6])
	k+=2
print(flag)
# cfa2b87b3f746a8f0ac5c5963f
# 第三部分
from z3 import *
s = Solver()
a1,a2,a3,a4,a5,a6 = Ints("a1 a2 a3 a4 a5 a6")
s.add(a1*3 + a2*2 + a3*5 == 1003)
s.add(a1*4 + a2*7 + a3*9 == 2013)
s.add(a1 + a2*8 + a3*2 == 1109)
s.add(a4*3 + a5*2 + a6*5 == 671)
s.add(a4*4 + a5*7 + a6*9 == 1252)
s.add(a4 + a5*8 + a6*2 == 644)
s.add(a1>0x20)
s.add(a1<0x7f)
if s.check()== sat:
    ans = s.model()
print(ans)
# [a5 = 55, a2 = 101, a6 = 51, a3 = 102, a4 = 102, a1 = 97]
print(bytes([97,101,102,102,55,51]))
# b'aeff73'

[NSSCTF 2nd]Bytecode

题目在nssctf靶场上,直接搜就有,txt文件内容有点长。就不放出来了;

手撸源代码是真的累啊,本来还有几题想复现的,但是写着写着就十点多了,下次有机会再继续了,这次就练倆题吧。

import base64
import string

def check(key):
    x = [78, 82, 81, 64, 80, 67, 125, 83, 96, 56, 121, 84, 61, 126, 81, 79, 79, 119, 38, 120, 39, 74, 112, 38, 44, 126, 103]
    if len(key) != len(x):
        print('Wrong length!')
        exit()
    for i in range(len(key)):
        if ord(key[i])^i != x[i]:
            return 0
        return 1

def init(key):
    s_box = list(range(256))
    j = 0
    for i in range(256):
        j = (j + s_box[i] + ord(key[i]%len(key))%256)
        s_box[j],s_box[i] = s_box[i],s_box[j]
    return s_box

def fun(key):
    key = "Just kidding, don't take it personally!"
    x = []
    for i in range(len(msg)):
        x.append(ord(msg[i]) ^ ord(key[i%len(key)]))
    for i in range(len(x)):
        x[i] = x[i] ^ x[(i + 1) % len(x)]
    return x

def encrypt1(msg, s_box):
    x = []
    i = 0
    j = 0
    for k in range(len(msg)):
        i = (i + 1) % 256
        j = (j + s_box[i]) % 256
        s_box[j], s_box[i] = s_box[i],s_box[j]
        t = (s_box[i] + s_box[j]) % 256
        x.append(ord(msg[k]) ^ s_box[t])
    return x

def encrtot2(msg, s_box):
    x = []
    i = 0
    j = 0
    for k in range(len(msg)):
        i = (i + 1) % 256
        j = (j + s_box[i]) % 256
        s_box[j], s_box[i] = s_box[i], s_box[j]
        t = (s_box[i] + s_box[j]) % 256
        x.append(ord(msg[k]) ^ s_box[t] ^ ord(key[i]))
    return x

def encrypt(msg, s_box):
    x = [[]]
    i = 0
    j = 0
    for k in range(len(msg)):
        i = (i + 1) % 256
        j = (j + s_box[i]) % 256
        s_box[j], s_box[i] = s_box[i], s_box[j]
        t = (s_box[i] + s_box[j]) % 256
        x.append(ord(msg[k]) ^ s_box[t] ^ i)
    return x

if __name__ == '__main__':
    key = input('Please input your key:')
    if check(key) == 1:
        print('Right!')
    else:
        print('Wrong!')
        exit()
    msg = input('Please input your message:')
    box = init(key)
    encode = encrypt(msg,box)
    string1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    string2 = 'YRiAOe4PlGvxaCoNj2ZgX+q8t/5Em6IUpM9FrVb7BKwsT1n3fSydhDWuQHJ0ckzL'
    encode = base64.b64encode(bytes(encode.translate(str.maketrans(string1,string2)))).decode('utf-8')
    if encode == 'mWGFL24R/RSZY3pzK9H4FOmFOnXJKyCjXWbZ7Ijy11GbCBukDrjsiPPFiYB=':
        print('Congraduation!You get the right flag!')
    else:
        print('Wrong!')

这一题的第29行,我其实也还不是很明白;

12a649a355d049b7805b7aa19de67e41.png

查了 DUP_TOP_TWO是用于在堆栈上复制最顶端的两个值,并将它们推送回堆栈。但是还是不很理解怎么操作的/(ㄒoㄒ)/~~,学习不到位了,明天接着继续研究了。

这道题我觉得烦就是手撸代码了,得到源代码就好多了

import base64

def init(key):
    s_box = list(range(256))
    j = 0
    for i in range(256):
        j = (j + s_box[i] + ord(key[i % len(key)])) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]
    return s_box

def decrypt(s_box, encoded_msg):
    decoded_msg = []
    i = 0
    j = 0
    for k in range(len(encoded_msg)):
        i = (i + 1) % 256
        j = (j + s_box[i]) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]
        t = (s_box[i] + s_box[j]) % 256
        decoded_msg.append(encoded_msg[k] ^ s_box[t] ^ i)
    return decoded_msg

key = "NSSCTF{Th1s_1s_@_f4k3_f14g}"
encoded_result = "mWGFL24R/RSZY3pzK9H4FOmFOnXJKyCjXWbZ7Ijy11GbCBukDrjsiPPFiYB="

string1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
string2 = 'YRiAOe4PlGvxaCoNj2ZgX+q8t/5Em6IUpM9FrVb7BKwsT1n3fSydhDWuQHJ0ckzL'

decoded_encoded_result=base64.b64decode(encoded_result.translate(str.maketrans(string2,string1)))

s_box = init(key)
decoded_message = decrypt(s_box, decoded_encoded_result)

message = ''.join(chr(c) for c in decoded_message)
print(message)

exp抄的别人/(ㄒoㄒ)/~~

 

后言

就先这样也了,不是很难手动反编译,主要就是麻烦,不过多练就好,加油咯。慢慢学~/(ㄒoㄒ)/~~,笨鸟多飞hh。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: solidity的bytecode是经过编译生成的字节码,其中包含了合约的二进制代码和一些元数据。如果你已经拥有了bytecode,那么你可以使用solidity的官方工具solc将bytecode转换成abi。在命令行中运行以下命令即可: ``` solc --abi <your_contract_bytecode> ``` 在这里,`<your_contract_bytecode>`是你的合约字节码。执行上述命令后,会生成一个JSON格式的abi文件,其中包含了你的合约的函数名、参数类型、返回类型等信息。 ### 回答2: 在Solidity中,字节码bytecode)是由智能合约源代码编译生成的机器码指令序列,而ABI(Application Binary Interface)是用于与合约进行交互的接口描述。反编译字节码以获取ABI的过程如下所示: 1. 使用Solidity编译器(solc)将Solidity源代码编译为字节码。这可以通过命令行工具(solc)或使用Solidity插件进行。 2. 获取编译后的字节码bytecode)。一般来说,编译器会生成合约的部署字节码和运行时字节码。部署字节码用于在区块链上创建新的合约实例,而运行时字节码用于执行合约中的方法。 3. 使用反编译工具将字节码反编译汇编代码。有几种工具可以实现这一步骤,如Etherscan的工具,它可以将部署字节码和运行时字节码转换为可读的汇编代码。 4. 根据反编译汇编代码推导出ABI。反编译汇编代码将显示每个函数的入口点和参数类型等信息。根据这些信息,可以手动创建ABI,或使用相关工具从汇编代码中提取并自动生成ABI。 需要注意的是,由于编译器的优化等因素,反编译得到的汇编代码可能不完全准确,某些信息(如内部函数、变量名)可能会丢失。因此,在实际应用中,最好使用在编译阶段生成的ABI,而不是依赖于反编译出来的版本。 ### 回答3: 要反编译 Solidity 的字节码bytecode)以获取 ABI(应用程序二进制接口),我们可以使用一些工具和步骤: 1. 使用 Solidity 编译器将智能合约源代码编译为字节码。例如,使用 solc 命令行工具:`solc --bin <contract_filename.sol>`。这将生成合约的字节码文件。 2. 将字节码转换为可读格式。字节码通常是以十六进制表示的。我们可以使用 Solidity 的库函数来将其转换为可读的格式。在 Solidity 中使用以下函数:`bytes memory bytecode = hex"字节码"`。 3. 使用反编译工具将字节码转换为 ABI。目前,有一些可用的工具可以帮助我们将 Solidity 字节码转换为 ABI。 - Solidity Assembly 是一种受到 EVM 指令集影响的低级语言。您可以使用 Solidity Assembly 编写代码并将其转换为 ABI。示例代码如下: ``` pragma solidity ^0.8.0; contract BytecodeParser { function getABI(bytes memory _bytecode) public pure returns (string[] memory) { assembly { let ptr := add(_bytecode, 0x20) let length := mload(_bytecode) let result := mload(0x40) // allocate memory for the ABI mstore(result, 0x20) // set length of the array to 1 mstore(add(result, 0x20), length) // store the length of the bytecode as the first element mstore(add(result, 0x40), ptr) // store the bytecode as the second element return(result, 0x60) } } } ``` - Mythril 是一个开源的智能合约扫描工具,也可以用于反编译 Solidity 字节码。安装 Mythril 并使用以下命令:`myth -x <Bytecode_File_Path>`。 - Remix IDE 是一个具有反编译功能的 Solidity 开发环境。在 Remix IDE 中,您可以上传字节码文件并选择反编译功能以获取 ABI。 请注意,由于 Solidity 字节码是通过编译过程中的优化生成的,所以在某些情况下,反编译出的 ABI 可能不完全准确。因此,在实际使用过程中,最好通过查看合约的源代码来获取准确的 ABI。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sciurdae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值