首页
社区
课程
招聘
[原创]pyd文件逆向
发表于: 2025-2-11 00:53 7436

[原创]pyd文件逆向

2025-2-11 00:53
7436

前言

在Python生态中,.pyd文件作为动态链接库形式的扩展模块,因其高效性和隐蔽性被广泛应用于代码保护、性能优化及跨语言开发。本文主要结合静态反汇编工具,剖析.pyd文件逆向的要点。

官方文档:

35bK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6U0P5i4c8Z5L8$3&6Q4x3X3g2J5k6h3q4V1N6r3S2W2k6r3!0U0M7#2)9J5k6h3W2G2i4K6u0r3k6h3&6Q4x3V1k6D9j5i4c8W2M7%4c8Q4x3V1k6K6M7X3y4Q4x3V1k6I4N6h3W2U0K9%4y4@1j5i4u0@1i4K6u0r3j5Y4g2A6L8r3c8Q4x3X3g2Z5N6r3#2D9

d64K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6U0P5i4c8Z5L8$3&6Q4x3X3g2G2M7X3N6Q4x3V1j5`.

编译

大致流程为: 编写py源代码以及对应的编译脚本-> 生成对应的.c 之类的中间文件 -> 调用编译器编译.c文件 -> 生成pyd文件可供使用

用户只需要配置好第一步即可

手动编译

按照官方文档编译一个 pyd 文件:

python pip 安装模块cython

1
pip install Cython

编写一个hello.pyx 脚本, 里面随便写一个函数

1
2
def say_hello_to(name):
    print(f"Hello {name}!")

在同目录编写一个 setup.py 脚本,里面的文件名为固定的内容,文件名为刚刚写的py脚本完整名称

1
2
3
4
5
6
7
from setuptools import setup
from Cython.Build import cythonize
 
setup(
    name='Hello world app',
    ext_modules=cythonize("hello.pyx"),
)

在命令行执行命令,来编译这个文件

1
python setup.py build_ext --inplace

编译成果后会在同级目录下生成很多东西:

build 目录 存放一些编译生成的中间文件

xxxx.c py文件到c源码文件,中间包含了完整的c代码(该文件并不会公布)

xxxxx.cpyyyy-win_amd64.pyd 编译好的文件xxxx 为py文件的命名 yyyy 为python的版本号 ,这个文件可只保留原始文件名和后缀.pyd 例如 bbbbb.cp312-win_amd64.pyd -> bbbbb.pyd

如果两个文件在同时在同级目录下,python会优先选择带版本号的,如果没有再选择不带版本号的文件

如何调用?

在同级目录下,直接打开python使用 import xxxx 即可调用

1
2
import hello
from hello import say_hello_to

查看xxxx.c

里面有非常多的结构,并且有python代码转换的c源代码,我们可以在这里看到cython的转换规则,和大体的逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
static PyObject *__pyx_pf_5bbbbb_say_hello_to(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_name) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("say_hello_to", 1);
 
  /* "bbbbb.pyx":4
 *
 * def say_hello_to(name):
 *  print(f"Hello {name}")             # <<<<<<<<<<<<<<
 */
  __pyx_t_1 = __Pyx_PyObject_FormatSimple(__pyx_v_name, __pyx_empty_unicode); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyUnicode_Concat(__pyx_kp_u_Hello, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_print, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
  /* "bbbbb.pyx":3
 *
 *
 * def say_hello_to(name):             # <<<<<<<<<<<<<<
 *  print(f"Hello {name}")
 */
 
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("bbbbb.say_hello_to", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

这里编译的没有带符号,所以逆向的话,ida载入,很多函数都是没有函数名称的

手动编译1 带符号

在Linux下默认带有符号,Windows下默认不带符号,需要增加参数来生成详细的PDB,并ida加载PDB才能看到更详细内容

我们可以通过修改setup.py 来编译一个带符号的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from setuptools import setup, Extension
from Cython.Build import cythonize
 
ext_module = [
    Extension(
        name="www",
        sources=["www.py"],
        extra_compile_args=["/Zi"],
        extra_link_args=["/DEBUG"]
    )
]
 
setup(
    name = "www",
    ext_modules = cythonize(ext_module,annotate=True)
)

也可以在命令行编译时,增加 --debug 参数,但需要在安装Python时勾选 Download debug binaries ,否则会提示 104: 无法打开文件“python312_d.lib”

手动编译2 linux 不带符号

linux 默认情况下,编译出来带有符号,我们可以通过调整编译选项来编一个一个不带符号的pyd文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from setuptools import setup, Extension
from Cython.Build import cythonize
 
 
extensions = [
    Extension(
            sources=["xxx.py"],
            name="xxx"
            extra_link_args=["-Wl,--strip-all"]
        ),
]
 
setup(
    ext_modules=cythonize(extensions),
)

各种表达式解析

函数

默认情况下, 对外函数,可以搜索名称, 因为是全局变量,所以,变量都会放在一起

查找引用,可以发现结构体:

windows 下会多出一层调用 pw -> pf , pf 是真正的地址

Windows Release 版本也是一致: 就是符号没有这么明显,要稍微熟悉一点pyd的结构体。

Linux 默认情况下没有,可能被编译器优化掉 了,但c语言源码上基本一致,pw->pf 函数名

模块内函数/变量引用

函数的结构体大多都放在一起的,可以上下查找有没有其他的函数,直接搜索函数名,有时候可能会搜不到

1
2
3
4
5
6
def get_list():
    return [1,2,3,4,991,776,229, 12.22]
 
def get_list1(index,end):
    a= get_list()
        return a

在模块中调用模块的内容,会先调用 PyDict_GetItem_KnownHash 中获取,

寻找引用,一般是在 pymod_exec 完成初始化, xxxx+38) + 24

可以看到确实是 get_list 这个函数

对比有符号的发现,+24 是 ob_type v2 是函数地址

模块调用

1
2
3
4
import socket
import subprocess
 
socket.socket(socket.AF_INET,socket.SOCK_STREAM)

调用后的模块地址在v6, 然后又传给v10, 就可以跟着v10,看看有没有发生其他动作 一般来说,会使用 PyObject_GetAttr 来获取属性

这种模块调用会有引用计数的特性, 可以看到 v17 为属性, 其中经过了 ob_refcnt ,比较经典。

再经过 Pyx_PyObject_FastCallDict 来调用,参数为 v21 v26

有时候ida 可能识别的参数不对,数组大小不对,需要手动判别,更改。

可以看到v21的具体内容为 AF_INET

v26 的内容为 SOCK_STREAM

基本上可以通过静态大致识别出一些关键代码

运算

加减乘除移位左移右移xor与或非

编写测试函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def test_calc(a):
    res = a + 1
    res = res -10
    res = res * 998
    res = res / 100
    res = res * 200
    res = res // 30
    res = res ** 3
    res = res << 3
    res = res ^ a
    res = hex(res)[2:]
    res = res + '00'
    res = int(res, 16)
    res = res >> 4
    res = res | 0xf
    res = res & 0x1f
    res = ~rsa
    return res
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
_typeobject *__fastcall _pyx_pf_5bbbbb_10test_calc(_object *__pyx_v_a, _object *__pyx_self, __int64 a3)
{
  _typeobject *v3; // r12
  _typeobject *v5; // rbx
  _object *pyx_int_1; // r9
  _typeobject *ob_type; // rax
  unsigned __int64 ob_refcnt; // r8
  __int64 v9; // rax
  unsigned __int64 v10; // r8
  const char *v11; // rsi
  int v12; // edi
  int v13; // ebp
  _object *p_ob_base; // rax
  unsigned __int64 v15; // rdx
  __int64 v16; // rax
  __int64 v17; // rdx
  __int64 v18; // r8
  __int64 v19; // r9
  unsigned __int64 v20; // rdx
  _object *v21; // rdi
  int *v22; // rcx
  bool v23; // zf
  _object *v24; // rax
  __int64 v25; // rdx
  __int64 v26; // r8
  __int64 v27; // r9
  _object *v28; // rdi
  int *v29; // rcx
  _object *pyx_int_100; // r8
  _object *v31; // rax
  __int64 v32; // rax
  __int64 v33; // rdx
  __int64 v34; // r8
  __int64 v35; // r9
  _object *v36; // rdi
  int *v37; // rcx
  _object *v38; // rax
  __int64 v39; // rdx
  __int64 v40; // r8
  __int64 v41; // r9
  __int64 v42; // rdi
  int *v43; // rcx
  _object *v44; // r8
  _object *pyx_int_30; // r9
  unsigned __int64 v46; // rdx
  int *v47; // rcx
  __int64 v48; // rax
  __int64 v49; // rdx
  __int64 v50; // r8
  __int64 v51; // r9
  __int64 v52; // rdi
  int v53; // r8d
  unsigned int v54; // ecx
  int v55; // edx
  unsigned int v56; // r8d
  __int64 v57; // rax
  signed __int64 v58; // r8
  unsigned __int64 v59; // rcx
  __int64 v60; // rdx
  unsigned __int64 v61; // r8
  int *v62; // rcx
  _object *v63; // r8
  _object *pyx_int_3; // r9
  unsigned __int64 v65; // rdx
  int *v66; // rcx
  __int64 v67; // rax
  __int64 v68; // rdx
  __int64 v69; // r8
  _object *v70; // r9
  _object *v71; // rdi
  unsigned __int64 v72; // rcx
  __int64 v73; // rax
  int *v74; // rcx
  _object *v75; // rax
  _object *v76; // r14
  _typeobject *v77; // r8
  PyMappingMethods *tp_as_mapping; // r15
  __int64 v79; // rdx
  _typeobject *v80; // rdi
  __int64 v81; // r8
  __int64 v82; // r9
  __int64 v83; // rax
  int *v84; // rdi
  int *v85; // rsi
  int *v86; // rcx
  __int64 v87; // rax
  __int64 v88; // rdx
  __int64 v89; // r8
  __int64 v90; // r9
  _object *v91; // r8
  __pyx_mstate *v92; // rdx
  _object *pyx_int_16; // rcx
  _object *v94; // rdi
  int *v95; // rcx
  _object *pyx_int_4; // r9
  unsigned __int64 v97; // rdx
  int *v98; // rcx
  _object *pyx_int_15; // rsi
  unsigned __int64 v100; // rcx
  __int64 v101; // rax
  unsigned __int64 v102; // rdx
  __int64 v103; // rax
  int v104; // ecx
  __int64 v105; // rax
  __int64 v106; // rdx
  __int64 v107; // r8
  __int64 v108; // r9
  int *v109; // rdi
  __int64 v110; // rdx
  __int64 v111; // r8
  __int64 v112; // r9
  _typeobject *v113; // r14
  _object *args; // [rsp+38h] [rbp-30h] BYREF
 
  v3 = 0i64;
  v5 = 0i64;
  pyx_int_1 = _pyx_mstate_global->__pyx_int_1;
  ob_type = __pyx_self->ob_type;
  if ( ob_type != (_typeobject *)PyLong_Type )
  {
    if ( ob_type == (_typeobject *)PyFloat_Type )
      v9 = PyFloat_FromDouble(__pyx_v_a, __pyx_self, a3, pyx_int_1);
    else
      v9 = PyNumber_Add(__pyx_self, _pyx_mstate_global->__pyx_int_1);
LABEL_14:
    pyx_int_1 = (_object *)v9;
    goto LABEL_15;
  }
  ob_refcnt = __pyx_self[1].ob_refcnt;
  if ( (ob_refcnt & 1) == 0 )
  {
    if ( ob_refcnt >= 0x10 )
    {
      v10 = ob_refcnt >> 3;
      switch ( v10 * (1 - (__pyx_self[1].ob_refcnt & 3)) )
      {
        case 0xFFFFFFFFFFFFFFFEui64:
          v9 = PyLong_FromLongLong(
                 1 - (LODWORD(__pyx_self[1].ob_type) | ((unsigned __int64)HIDWORD(__pyx_self[1].ob_type) << 30)),
                 __pyx_self,
                 v10,
                 pyx_int_1);
          break;
        case 2ui64:
          v9 = PyLong_FromLongLong(
                 (LODWORD(__pyx_self[1].ob_type) | ((unsigned __int64)HIDWORD(__pyx_self[1].ob_type) << 30)) + 1,
                 __pyx_self,
                 v10,
                 pyx_int_1);
          break;
        default:
          v9 = (**((__int64 (__fastcall ***)(_object *, _object *))&PyLong_Type + 12))(
                 __pyx_self,
                 _pyx_mstate_global->__pyx_int_1);
          break;
      }
    }
    else
    {
      v9 = PyLong_FromLong(LODWORD(__pyx_self[1].ob_type) * (1 - (unsigned int)(ob_refcnt & 3)) + 1);
    }
    goto LABEL_14;
  }
  if ( pyx_int_1->ob_refcnt_split[0] != -1 )
    ++pyx_int_1->ob_refcnt_split[0];
LABEL_15:
  if ( !pyx_int_1 )
  {
    v11 = _pyx_f[0];
    v12 = 42;
    v13 = 3937;
    goto LABEL_204;
  }
  v5 = (_typeobject *)pyx_int_1;
  p_ob_base = &pyx_int_1->ob_type->ob_base.ob_base;
  if ( p_ob_base == PyLong_Type )
  {
    v15 = pyx_int_1[1].ob_refcnt;
    if ( (v15 & 1) != 0 )
    {
      v16 = PyLong_FromLong(0xFFFFFFF6i64);
    }
    else if ( v15 >= 0x10 )
    {
      v20 = v15 >> 3;
      switch ( v20 * (1 - (pyx_int_1[1].ob_refcnt & 3)) )
      {
        case 0xFFFFFFFFFFFFFFFEui64:
          v16 = PyLong_FromLongLong(
                  -(__int64)(LODWORD(pyx_int_1[1].ob_type) | ((unsigned __int64)HIDWORD(pyx_int_1[1].ob_type) << 30))
                - 10,
                  v20,
                  ob_refcnt,
                  pyx_int_1);
          break;
        case 2ui64:
          v16 = PyLong_FromLongLong(
                  (LODWORD(pyx_int_1[1].ob_type) | ((unsigned __int64)HIDWORD(pyx_int_1[1].ob_type) << 30)) - 10,
                  v20,
                  ob_refcnt,
                  pyx_int_1);
          break;
        default:
          v16 = (*(__int64 (__fastcall **)(_object *, _object *))(*((_QWORD *)&PyLong_Type + 12) + 8i64))(
                  pyx_int_1,
                  _pyx_mstate_global->__pyx_int_10);
          break;
      }
    }
    else
    {
      v16 = PyLong_FromLong(LODWORD(pyx_int_1[1].ob_type) * (1 - (unsigned int)(v15 & 3)) - 10);
    }
  }
  else if ( p_ob_base == (_object *)PyFloat_Type )
  {
    v16 = PyFloat_FromDouble(__pyx_v_a, __pyx_self, ob_refcnt, pyx_int_1);
  }
  else
  {
    v16 = PyNumber_Subtract(pyx_int_1, _pyx_mstate_global->__pyx_int_10);
  }
  v21 = (_object *)v16;
  if ( !v16 )
  {
    v11 = _pyx_f[0];
    v12 = 43;
    v13 = 3949;
    goto LABEL_204;
  }
  v22 = (int *)v5;
  v5 = (_typeobject *)v16;
  if ( *v22 >= 0 )
  {
    v23 = (*(_QWORD *)v22)-- == 1i64;
    if ( v23 )
      _Py_Dealloc(v22, v17, v18, v19);
  }
  v24 = _Pyx_PyInt_MultiplyObjC(v21, _pyx_mstate_global->__pyx_int_998, 998i64, v19);
  v28 = v24;
  if ( !v24 )
  {
    v11 = _pyx_f[0];
    v12 = 44;
    v13 = 3961;
    goto LABEL_204;
  }
  v29 = (int *)v5;
  v5 = (_typeobject *)v24;
  if ( *v29 >= 0 )
  {
    v23 = (*(_QWORD *)v29)-- == 1i64;
    if ( v23 )
      _Py_Dealloc(v29, v25, v26, v27);
  }
  pyx_int_100 = _pyx_mstate_global->__pyx_int_100;
  v31 = &v28->ob_type->ob_base.ob_base;
  if ( v31 == PyLong_Type )
  {
    if ( v28[1].ob_refcnt >= 0x10ui64 )
      v32 = (*(__int64 (__fastcall **)(_object *, _object *))(*((_QWORD *)&PyLong_Type + 12) + 240i64))(
              v28,
              _pyx_mstate_global->__pyx_int_100);
    else
      v32 = PyFloat_FromDouble(v28[1].ob_refcnt & 3, PyLong_Type, pyx_int_100, v27);
  }
  else if ( v31 == (_object *)PyFloat_Type )
  {
    v32 = PyFloat_FromDouble(v29, PyLong_Type, pyx_int_100, v27);
  }
  else
  {
    v32 = PyNumber_TrueDivide(v28, _pyx_mstate_global->__pyx_int_100);
  }
  v36 = (_object *)v32;
  if ( !v32 )
  {
    v11 = _pyx_f[0];
    v12 = 45;
    v13 = 3973;
    goto LABEL_204;
  }
  v37 = (int *)v5;
  v5 = (_typeobject *)v32;
  if ( *v37 >= 0 )
  {
    v23 = (*(_QWORD *)v37)-- == 1i64;
    if ( v23 )
      _Py_Dealloc(v37, v33, v34, v35);
  }
  v38 = _Pyx_PyInt_MultiplyObjC(v36, _pyx_mstate_global->__pyx_int_200, 200i64, v35);
  v42 = (__int64)v38;
  if ( !v38 )
  {
    v11 = _pyx_f[0];
    v12 = 46;
    v13 = 3985;
    goto LABEL_204;
  }
  v43 = (int *)v5;
  v5 = (_typeobject *)v38;
  if ( *v43 >= 0 )
  {
    v23 = (*(_QWORD *)v43)-- == 1i64;
    if ( v23 )
      _Py_Dealloc(v43, v39, v40, v41);
  }
  v44 = PyLong_Type;
  pyx_int_30 = _pyx_mstate_global->__pyx_int_30;
  if ( *(_object *const *)(v42 + 8) == PyLong_Type )
  {
    v46 = *(_QWORD *)(v42 + 16);
    if ( (v46 & 1) != 0 )
    {
      if ( *(_DWORD *)v42 != -1 )
        ++*(_DWORD *)v42;
      goto LABEL_60;
    }
    if ( v46 >= 0x10 )
    {
      switch ( (*(_QWORD *)(v42 + 16) >> 3) * (1 - (*(_QWORD *)(v42 + 16) & 3ui64)) )
      {
        case 0xFFFFFFFFFFFFFFFEui64:
          v58 = -(__int64)(*(unsigned int *)(v42 + 24) | ((unsigned __int64)*(unsigned int *)(v42 + 28) << 30));
          goto LABEL_72;
        case 2ui64:
          v58 = *(unsigned int *)(v42 + 24) | ((unsigned __int64)*(unsigned int *)(v42 + 28) << 30);
LABEL_72:
          v59 = 0i64;
          v60 = v58 / 30;
          v61 = v58 % 30;
          if ( v61 )
            v59 = v61 >> 63;
          v57 = PyLong_FromLongLong(v60 - v59, v60 - v59, v61, pyx_int_30);
          break;
        default:
          v57 = (*(__int64 (__fastcall **)(__int64, _object *))(*((_QWORD *)&PyLong_Type + 12) + 232i64))(
                  v42,
                  _pyx_mstate_global->__pyx_int_30);
          break;
      }
    }
    else
    {
      v53 = *(_DWORD *)(v42 + 24) * (1 - (v46 & 3));
      v54 = 0;
      v55 = v53 / 30;
      v56 = v53 % 30;
      if ( v56 )
        v54 = v56 >> 31;
      v57 = PyLong_FromLong(v55 - v54);
    }
  }
  else
  {
    v57 = PyNumber_FloorDivide(v42, _pyx_mstate_global->__pyx_int_30);
  }
  v42 = v57;
  if ( !v57 )
  {
    v11 = _pyx_f[0];
    v12 = 47;
    v13 = 3997;
    goto LABEL_204;
  }
LABEL_60:
  v47 = (int *)v5;
  v5 = (_typeobject *)v42;
  if ( *v47 >= 0 )
  {
    v23 = (*(_QWORD *)v47)-- == 1i64;
    if ( v23 )
      _Py_Dealloc(v47, v46, v44, pyx_int_30);
  }
  v48 = PyNumber_Power(v42, _pyx_mstate_global->__pyx_int_3, _Py_NoneStruct, pyx_int_30);
  v52 = v48;
  if ( !v48 )
  {
    v11 = _pyx_f[0];
    v12 = 48;
    v13 = 4009;
    goto LABEL_204;
  }
  v62 = (int *)v5;
  v5 = (_typeobject *)v48;
  if ( *v62 >= 0 )
  {
    v23 = (*(_QWORD *)v62)-- == 1i64;
    if ( v23 )
      _Py_Dealloc(v62, v49, v50, v51);
  }
  v63 = PyLong_Type;
  pyx_int_3 = _pyx_mstate_global->__pyx_int_3;
  if ( *(_object *const *)(v52 + 8) != PyLong_Type )
  {
LABEL_102:
    v73 = PyNumber_Lshift(v52, _pyx_mstate_global->__pyx_int_3);
    goto LABEL_103;
  }
  v65 = *(_QWORD *)(v52 + 16);
  if ( (v65 & 1) != 0 )
  {
    if ( *(_DWORD *)v52 != -1 )
      ++*(_DWORD *)v52;
    goto LABEL_86;
  }
  if ( v65 < 0x10 )
  {
    LODWORD(v72) = *(_DWORD *)(v52 + 24) * (1 - (v65 & 3));
    if ( (_DWORD)v72 == (8 * (int)v72) >> 3 || !(_DWORD)v72 )
    {
      v73 = PyLong_FromLong((unsigned int)(8 * v72));
      goto LABEL_103;
    }
    v72 = (int)v72;
LABEL_99:
    if ( v72 == (__int64)(8 * v72) >> 3 )
    {
      v73 = PyLong_FromLongLong(8 * v72, 8 * v72, PyLong_Type, pyx_int_3);
      goto LABEL_103;
    }
    goto LABEL_102;
  }
  switch ( (*(_QWORD *)(v52 + 16) >> 3) * (1 - (*(_QWORD *)(v52 + 16) & 3ui64)) )
  {
    case 0xFFFFFFFFFFFFFFFEui64:
      v72 = -(__int64)(*(unsigned int *)(v52 + 24) | ((unsigned __int64)*(unsigned int *)(v52 + 28) << 30));
      goto LABEL_99;
    case 2ui64:
      v72 = *(unsigned int *)(v52 + 24) | ((unsigned __int64)*(unsigned int *)(v52 + 28) << 30);
      goto LABEL_99;
    default:
      v73 = (*(__int64 (__fastcall **)(__int64, _object *))(*((_QWORD *)&PyLong_Type + 12) + 88i64))(
              v52,
              _pyx_mstate_global->__pyx_int_3);
      break;
  }
LABEL_103:
  v52 = v73;
  if ( !v73 )
  {
    v11 = _pyx_f[0];
    v12 = 49;
    v13 = 4021;
    goto LABEL_204;
  }
LABEL_86:
  v66 = (int *)v5;
  v5 = (_typeobject *)v52;
  if ( *v66 >= 0 )
  {
    v23 = (*(_QWORD *)v66)-- == 1i64;
    if ( v23 )
      _Py_Dealloc(v66, v65, v63, pyx_int_3);
  }
  v67 = PyNumber_Xor(v52, __pyx_self, v63, pyx_int_3);
  v71 = (_object *)v67;
  if ( !v67 )
  {
    v11 = _pyx_f[0];
    v12 = 50;
    v13 = 4033;
    goto LABEL_204;
  }
  v74 = (int *)v5;
  v5 = (_typeobject *)v67;
  if ( *v74 >= 0 )
  {
    v23 = (*(_QWORD *)v74)-- == 1i64;
    if ( v23 )
      _Py_Dealloc(v74, v68, v69, v70);
  }
  args = v71;
  v75 = _Pyx_PyObject_FastCallDict(_pyx_builtin_hex, &args, 0x8000000000000001ui64, v70);
  v76 = v75;
  if ( !v75 )
  {
    v11 = _pyx_f[0];
    v12 = 51;
    v13 = 4045;
    goto LABEL_204;
  }
  v77 = v75->ob_type;
  tp_as_mapping = v77->tp_as_mapping;
  if ( !tp_as_mapping || !tp_as_mapping->mp_subscript )
  {
    PyErr_Format(PyExc_TypeError, "'%.200s' object is unsliceable", v77->tp_name);
    goto LABEL_200;
  }
  if ( _pyx_mstate_global == (__pyx_mstate *)-656i64 )
  {
    v83 = PyLong_FromSsize_t(2i64);
    v84 = (int *)v83;
    if ( !v83 )
      goto LABEL_200;
    v85 = (int *)PySlice_New(v83, _Py_NoneStruct, _Py_NoneStruct);
    if ( *v84 >= 0 )
    {
      v23 = (*(_QWORD *)v84)-- == 1i64;
      if ( v23 )
        _Py_Dealloc(v84, v79, v81, v82);
    }
    if ( !v85 )
      goto LABEL_200;
    v80 = (_typeobject *)tp_as_mapping->mp_subscript(v76, (_object *)v85);
    if ( *v85 >= 0 )
    {
      v23 = (*(_QWORD *)v85)-- == 1i64;
      if ( v23 )
        _Py_Dealloc(v85, v79, v81, v82);
    }
  }
  else
  {
    v80 = (_typeobject *)tp_as_mapping->mp_subscript(v75, _pyx_mstate_global->__pyx_slice__4);
  }
  if ( !v80 )
  {
LABEL_200:
    v12 = 51;
    v13 = 4047;
    goto $__pyx_L1_error_2;
  }
  if ( (v76->ob_refcnt_split[0] & 0x80000000) == 0 )
  {
    v23 = v76->ob_refcnt-- == 1;
    if ( v23 )
      _Py_Dealloc(v76, v79, v81, v82);
  }
  v86 = (int *)v5;
  v5 = v80;
  if ( *v86 >= 0 )
  {
    v23 = (*(_QWORD *)v86)-- == 1i64;
    if ( v23 )
      _Py_Dealloc(v86, v79, v81, v82);
  }
  v87 = PyNumber_Add(v80, _pyx_mstate_global->__pyx_kp_s_00);
  if ( !v87 )
  {
    v11 = _pyx_f[0];
    v12 = 52;
    v13 = 4060;
    goto LABEL_204;
  }
  v5 = (_typeobject *)v87;
  if ( (v80->ob_base.ob_base.ob_refcnt_split[0] & 0x80000000) == 0 )
  {
    v23 = v80->ob_base.ob_base.ob_refcnt-- == 1;
    if ( v23 )
      _Py_Dealloc(v80, v88, v89, v90);
  }
  v76 = (_object *)PyTuple_New(2i64);
  if ( !v76 )
  {
    v11 = _pyx_f[0];
    v12 = 53;
    v13 = 4072;
    goto LABEL_204;
  }
  if ( v5->ob_base.ob_base.ob_refcnt_split[0] != -1 )
    ++v5->ob_base.ob_base.ob_refcnt_split[0];
  v92 = _pyx_mstate_global;
  v76[1].ob_type = v5;
  pyx_int_16 = v92->__pyx_int_16;
  if ( pyx_int_16->ob_refcnt_split[0] != -1 )
    ++pyx_int_16->ob_refcnt_split[0];
  v76[2].ob_refcnt = (__int64)v92->__pyx_int_16;
  v94 = _Pyx_PyObject_Call(PyLong_Type, v76, v91);
  if ( !v94 )
  {
    v12 = 53;
    v13 = 4080;
$__pyx_L1_error_2:
    v11 = _pyx_f[0];
    if ( (v76->ob_refcnt_split[0] & 0x80000000) == 0 )
    {
      v23 = v76->ob_refcnt-- == 1;
      if ( v23 )
        _Py_Dealloc(v76, v79, v81, v82);
    }
LABEL_204:
    v113 = v5;
    _Pyx_AddTraceback("bbbbb.test_calc", v13, v12, v11);
    if ( !v5 )
      return v3;
    goto LABEL_205;
  }
  if ( (v76->ob_refcnt_split[0] & 0x80000000) == 0 )
  {
    v23 = v76->ob_refcnt-- == 1;
    if ( v23 )
      _Py_Dealloc(v76, v79, v81, v82);
  }
  v95 = (int *)v5;
  v5 = (_typeobject *)v94;
  if ( *v95 >= 0 )
  {
    v23 = (*(_QWORD *)v95)-- == 1i64;
    if ( v23 )
      _Py_Dealloc(v95, v79, v81, v82);
  }
  pyx_int_4 = _pyx_mstate_global->__pyx_int_4;
  if ( (_object *const)v94->ob_type == PyLong_Type )
  {
    v97 = v94[1].ob_refcnt;
    if ( (v97 & 1) != 0 )
    {
      if ( v94->ob_refcnt_split[0] != -1 )
        ++v94->ob_refcnt_split[0];
      goto LABEL_152;
    }
    if ( v97 >= 0x10 )
    {
      v102 = v97 >> 3;
      switch ( v102 * (1 - (v94[1].ob_refcnt & 3)) )
      {
        case 0xFFFFFFFFFFFFFFFEui64:
          v101 = PyLong_FromLongLong(
                   -(__int64)(LODWORD(v94[1].ob_type) | ((unsigned __int64)HIDWORD(v94[1].ob_type) << 30)) >> 4,
                   v102,
                   v81,
                   pyx_int_4);
          break;
        case 2ui64:
          v101 = PyLong_FromLongLong(
                   (__int64)(LODWORD(v94[1].ob_type) | ((unsigned __int64)HIDWORD(v94[1].ob_type) << 30)) >> 4,
                   v102,
                   v81,
                   pyx_int_4);
          break;
        default:
          v101 = (*(__int64 (__fastcall **)(_object *, _object *))(*((_QWORD *)&PyLong_Type + 12) + 96i64))(
                   v94,
                   _pyx_mstate_global->__pyx_int_4);
          break;
      }
    }
    else
    {
      v101 = PyLong_FromLong((unsigned int)((int)(LODWORD(v94[1].ob_type) * (1 - (v97 & 3))) >> 4));
    }
  }
  else
  {
    v101 = PyNumber_Rshift(v94, _pyx_mstate_global->__pyx_int_4);
  }
  v94 = (_object *)v101;
  if ( !v101 )
  {
    v11 = _pyx_f[0];
    v12 = 54;
    v13 = 4093;
    goto LABEL_204;
  }
LABEL_152:
  v98 = (int *)v5;
  v5 = (_typeobject *)v94;
  if ( *v98 >= 0 )
  {
    v23 = (*(_QWORD *)v98)-- == 1i64;
    if ( v23 )
      _Py_Dealloc(v98, v97, v81, pyx_int_4);
  }
  pyx_int_15 = _pyx_mstate_global->__pyx_int_15;
  if ( (_object *const)v94->ob_type != PyLong_Type )
  {
    v103 = PyNumber_Or(v94, _pyx_mstate_global->__pyx_int_15, v81, pyx_int_4);
LABEL_175:
    pyx_int_15 = (_object *)v103;
    goto LABEL_176;
  }
  v100 = v94[1].ob_refcnt;
  if ( (v100 & 1) == 0 )
  {
    if ( v100 >= 0x10 )
    {
      switch ( (v100 >> 3) * (1 - (v94[1].ob_refcnt & 3)) )
      {
        case 0xFFFFFFFFFFFFFFFEui64:
          v103 = PyLong_FromLongLong(
                   -(__int64)(LODWORD(v94[1].ob_type) | ((unsigned __int64)HIDWORD(v94[1].ob_type) << 30)) | 0xF,
                   v97,
                   v81,
                   pyx_int_4);
          break;
        case 2ui64:
          v103 = PyLong_FromLongLong(
                   LODWORD(v94[1].ob_type) | ((unsigned __int64)HIDWORD(v94[1].ob_type) << 30) | 0xF,
                   v97,
                   v81,
                   pyx_int_4);
          break;
        default:
          v103 = (*(__int64 (__fastcall **)(_object *, _object *, _QWORD, _object *))(*((_QWORD *)&PyLong_Type + 12)
                                                                                    + 120i64))(
                   v94,
                   _pyx_mstate_global->__pyx_int_15,
                   *((_QWORD *)&PyLong_Type + 12),
                   pyx_int_4);
          break;
      }
    }
    else
    {
      v103 = PyLong_FromLong((LODWORD(v94[1].ob_type) * (1 - (v100 & 3))) | 0xF);
    }
    goto LABEL_175;
  }
  if ( pyx_int_15->ob_refcnt_split[0] != -1 )
    ++pyx_int_15->ob_refcnt_split[0];
LABEL_176:
  if ( !pyx_int_15 )
  {
    v11 = _pyx_f[0];
    v12 = 55;
    v13 = 4105;
    goto LABEL_204;
  }
  v5 = (_typeobject *)pyx_int_15;
  if ( (v94->ob_refcnt_split[0] & 0x80000000) == 0 )
  {
    v23 = v94->ob_refcnt-- == 1;
    if ( v23 )
      _Py_Dealloc(v94, v97, v81, pyx_int_4);
  }
  if ( (_object *const)pyx_int_15->ob_type == PyLong_Type )
  {
    v104 = 0x40000000 - LODWORD(pyx_int_15[1].ob_type);
    if ( (pyx_int_15[1].ob_refcnt & 3) == 0 )
      v104 = (int)pyx_int_15[1].ob_type;
    v105 = PyLong_FromLong(v104 & 0x1F);
  }
  else
  {
    v105 = PyNumber_And(pyx_int_15, _pyx_mstate_global->__pyx_int_31, v81, pyx_int_4);
  }
  v109 = (int *)v105;
  if ( !v105 )
  {
    v11 = _pyx_f[0];
    v12 = 56;
    v13 = 4117;
    goto LABEL_204;
  }
  v5 = (_typeobject *)v105;
  if ( (pyx_int_15->ob_refcnt_split[0] & 0x80000000) == 0 )
  {
    v23 = pyx_int_15->ob_refcnt-- == 1;
    if ( v23 )
      _Py_Dealloc(pyx_int_15, v106, v107, v108);
  }
  v113 = (_typeobject *)PyNumber_Invert(v109);
  if ( !v113 )
  {
    v11 = _pyx_f[0];
    v12 = 57;
    v13 = 4129;
    goto LABEL_204;
  }
  if ( *v109 >= 0 )
  {
    v23 = (*(_QWORD *)v109)-- == 1i64;
    if ( v23 )
      _Py_Dealloc(v109, v110, v111, v112);
  }
  if ( v113->ob_base.ob_base.ob_refcnt_split[0] != -1 )
    ++v113->ob_base.ob_base.ob_refcnt_split[0];
  v3 = v113;
LABEL_205:
  if ( (v113->ob_base.ob_base.ob_refcnt_split[0] & 0x80000000) == 0 )
  {
    v23 = v113->ob_base.ob_base.ob_refcnt-- == 1;
    if ( v23 )
      _Py_Dealloc(v113, v110, v111, v112);
  }
  return v3;
}

ida 打开,找到相关函数

说明,紫色的变量/函数名为从别处导入的内容,在抹除符号情况下也能被识别出来

加法 +1 PyNumber_Add(__pyx_self, _pyx_mstate_global->__pyx_int_1); 如果是原地的话, 即 al += 1; 则可能会调用到 PyNumber_InPlaceAdd

-10 PyNumber_Subtract(pyx_int_1, _pyx_mstate_global->__pyx_int_10);

乘以 998 _Pyx_PyInt_MultiplyObjC(v21, _pyx_mstate_global->__pyx_int_998, 998i64, v19);

这里的乘法是经过了一层封装的,无符号情况下需要进入到里面才能看到实际的从导入表中调用的函数 PyNumber_Multiply(op1, op2, intval); 这里其他的运算函数也可能会这么封装,注意用此方法识别。

除以100 不取整 真除 PyNumber_TrueDivide(v28, _pyx_mstate_global->__pyx_int_100);

乘以200 _Pyx_PyInt_MultiplyObjC(v36, _pyx_mstate_global->__pyx_int_200, 200i64, v35);

地板除 30 即 整除 30 PyNumber_FloorDivide(v42, _pyx_mstate_global->__pyx_int_30);

3次方 PyNumber_Power(v42, _pyx_mstate_global->__pyx_int_3, _Py_NoneStruct, pyx_int_30);

左移 3 PyNumber_Lshift(v52, _pyx_mstate_global->__pyx_int_3);

xor PyNumber_Xor(v52, __pyx_self, v63, pyx_int_3);

FastCall 调用 内建函数 hex _Pyx_PyObject_FastCallDict(_pyx_builtin_hex, &args, 0x8000000000000001ui64, v70);

FastCall不是导入函数,进入到该函数内部可以看到调用了 PyObject_VectorcallDict ,可以依此为特征

切片操作 从2 开始 PySlice_New(v83, _Py_NoneStruct, _Py_NoneStruct);

字符串加法,加"00" PyNumber_Add(v80, _pyx_mstate_global->__pyx_kp_s_00);

强转类型, _Pyx_PyObject_Call(PyLong_Type, v76, v91); 第一个参数为类型 PyLong_Type 整型 int。

类型强转函数在无符号情况下,没有符号,需要进入到里面识别一下, 特征也是非常明显,传递的第一个参数是类型名,是一个紫色的被导入的函数/变量,函数内部也会有一些字符串来辅助识别,最后也是调用 PyObject_Call

右移 4 PyNumber_Rshift(v94, _pyx_mstate_global->__pyx_int_4);

或操作 PyNumber_Or(v94, _pyx_mstate_global->__pyx_int_15, v81, pyx_int_4);

与操作, 与 31 PyNumber_And(pyx_int_15, _pyx_mstate_global->__pyx_int_31, v81, pyx_int_4);

取反 (_typeobject *)PyNumber_Invert(v109);

技巧: 有些会运算先执行一遍,做一些判断?最终的运算还是调用导入的函数。所以需要仔细观察导入的函数和被调用的函数。

其中还会穿插一些引用计数的内容。

在无符号情况下,_pyx_mstate_global 结构体是不会识别出来的,需要手动从数据初始化部分来识别。

幂运算pow

rsa 相关

1
2
3
4
5
def rsa_enc(e,n,c):
    a = pow(c, 0x10001, 10403)
    b = c ** 0x10001, 10403
    d = pow(c, e, n)
    return a,b,d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
_object *__fastcall _pyx_pf_5bbbbb_8rsa_enc(
        _object *__pyx_v_e,
        _object *__pyx_v_n,
        _object *__pyx_v_c,
        _object *__pyx_self)
{
  _QWORD *v4; // rbp
  _DWORD *v5; // rdi
  int *v6; // rsi
  _DWORD *v9; // r14
  __int64 v10; // rax
  int v11; // r15d
  int v12; // r13d
  __int64 v13; // rbx
  unsigned __int64 v14; // rcx
  int *v15; // r15
  bool v16; // zf
  __int64 v17; // rax
  unsigned int v18; // r8d
  unsigned int v19; // eax
  __int64 v20; // rax
  signed __int64 v21; // r8
  unsigned __int64 v22; // r8
  unsigned __int64 v23; // rax
  const char *v24; // r12
  _QWORD *v25; // rax
 
  v4 = 0i64;
  v5 = 0i64;
  v6 = 0i64;
  v9 = 0i64;
  v10 = PyNumber_Power(__pyx_self, _pyx_mstate_global->__pyx_int_65537, _pyx_mstate_global->__pyx_int_10403);
  if ( !v10 )
  {
    v11 = 33;
    v12 = 3744;
LABEL_33:
    v24 = _pyx_f[0];
    goto LABEL_34;
  }
  v9 = (_DWORD *)v10;
  v13 = PyNumber_Power(__pyx_self, _pyx_mstate_global->__pyx_int_65537, _Py_NoneStruct);
  if ( !v13 )
  {
    v11 = 34;
    v12 = 3756;
    goto LABEL_33;
  }
  if ( *(_object *const *)(v13 + 8) == PyLong_Type )
  {
    v14 = *(_QWORD *)(v13 + 16);
    if ( (v14 & 1) != 0 )
    {
      if ( *(_DWORD *)v13 != -1 )
        ++*(_DWORD *)v13;
      v15 = (int *)v13;
      goto LABEL_10;
    }
    if ( v14 >= 0x10 )
    {
      switch ( (v14 >> 3) * (1 - (*(_QWORD *)(v13 + 16) & 3i64)) )
      {
        case 0xFFFFFFFFFFFFFFFEui64:
          v21 = -(__int64)(*(unsigned int *)(v13 + 24) | ((unsigned __int64)*(unsigned int *)(v13 + 28) << 30));
          goto LABEL_22;
        case 2ui64:
          v21 = *(unsigned int *)(v13 + 24) | ((unsigned __int64)*(unsigned int *)(v13 + 28) << 30);
LABEL_22:
          v22 = v21 % 10455;
          v23 = 0i64;
          if ( v22 )
            v23 = v22 >> 63;
          v20 = PyLong_FromLongLong(v22 + 10455 * v23);
          break;
        default:
          v20 = (*(__int64 (__fastcall **)(__int64, _object *))(*((_QWORD *)&PyLong_Type + 12) + 24i64))(
                  v13,
                  _pyx_mstate_global->__pyx_int_10455);
          break;
      }
    }
    else
    {
      v18 = (int)(*(_DWORD *)(v13 + 24) * (1 - (v14 & 3))) % 10455;
      v19 = 0;
      if ( v18 )
        v19 = v18 >> 31;
      v20 = PyLong_FromLong(v18 + 10455 * v19);
    }
  }
  else
  {
    v20 = PyNumber_Remainder(v13, _pyx_mstate_global->__pyx_int_10455);
  }
  v15 = (int *)v20;
  if ( !v20 )
  {
    v24 = _pyx_f[0];
    v11 = 34;
    v12 = 3758;
    if ( *(int *)v13 >= 0 )
    {
      v16 = (*(_QWORD *)v13)-- == 1i64;
      if ( v16 )
        _Py_Dealloc(v13);
    }
LABEL_34:
    _Pyx_AddTraceback("bbbbb.rsa_enc", v12, v11, v24);
    if ( !v9 )
      goto LABEL_46;
    goto LABEL_43;
  }
LABEL_10:
  if ( *(int *)v13 >= 0 )
  {
    v16 = (*(_QWORD *)v13)-- == 1i64;
    if ( v16 )
      _Py_Dealloc(v13);
  }
  v6 = v15;
  v17 = PyNumber_Power(__pyx_self, __pyx_v_n, __pyx_v_c);
  if ( !v17 )
  {
    v11 = 35;
    v12 = 3771;
    goto LABEL_33;
  }
  v5 = (_DWORD *)v17;
  v25 = (_QWORD *)PyTuple_New(3i64);
  if ( !v25 )
  {
    v11 = 36;
    v12 = 3784;
    goto LABEL_33;
  }
  if ( *v9 != -1 )
    ++*v9;
  v25[3] = v9;
  if ( *v15 != -1 )
    ++*v15;
  v25[4] = v15;
  if ( *v5 != -1 )
    ++*v5;
  v25[5] = v5;
  v4 = v25;
LABEL_43:
  if ( (int)*v9 >= 0 )
  {
    v16 = (*(_QWORD *)v9)-- == 1i64;
    if ( v16 )
      _Py_Dealloc(v9);
  }
LABEL_46:
  if ( v6 )
  {
    if ( *v6 >= 0 )
    {
      v16 = (*(_QWORD *)v6)-- == 1i64;
      if ( v16 )
        _Py_Dealloc(v6);
    }
  }
  if ( v5 )
  {
    if ( (int)*v5 >= 0 )
    {
      v16 = (*(_QWORD *)v5)-- == 1i64;
      if ( v16 )
        _Py_Dealloc(v5);
    }
  }
  return (_object *)v4;
}

PyNumber_Power(__pyx_self, _pyx_mstate_global->__pyx_int_65537, _pyx_mstate_global->__pyx_int_10403, __pyx_self); pow 参数 第一个原始数,第二个e次方,第三个 mod数

第二个运算形式是先有一个pow 取次幂,再有一个取模

v13 = PyNumber_Power(__pyx_self, _pyx_mstate_global->__pyx_int_65537, _Py_NoneStruct);

PyNumber_Remainder(v13, _pyx_mstate_global->__pyx_int_10455);

第三个就是取参数

数据类型及强转

元组 列表

取上面函数的例子:

1
2
3
4
5
def rsa_enc(e,n,c):
    a = pow(c, 0x10001, 10403)
    b = c ** 0x10001, 10403
    d = pow(c, e, n)
    return a,b,d

部分汇编代码,三个变量的由来,最后的组成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  v9 = 0i64;
  v10 = PyNumber_Power(__pyx_self, _pyx_mstate_global->__pyx_int_65537, _pyx_mstate_global->__pyx_int_10403);
  if ( !v10 )
  {
    v11 = 33;
    v12 = 3744;
LABEL_33:
    v24 = _pyx_f[0];
    goto LABEL_34;
  }
  v9 = (_DWORD *)v10;
 
  .......
  ........
   
    v20 = PyNumber_Remainder(v13, _pyx_mstate_global->__pyx_int_10455);
  }
  v15 = (int *)v20;
   
  .......
  ........
  v5 = (_DWORD *)v17;
  v25 = (_QWORD *)PyTuple_New(3i64);
  if ( !v25 )
  {
    v11 = 36;
    v12 = 3784;
    goto LABEL_33;
  }
  if ( *v9 != -1 )
    ++*v9;
  v25[3] = v9;
  if ( *v15 != -1 )
    ++*v15;
  v25[4] = v15;
  if ( *v5 != -1 )
    ++*v5;
  v25[5] = v5;
  v4 = v25;

可以看到,元组的第三个qword才是真实的数据存储, 初始化时会调用 PyTuple_New 函数

列表初始化, 基本上也差不多,很有规律

1
2
def get_list():
    return [1,2,3,4,991,776,229,"aaa","str", 12.22]

切片,上面的运算里面稍微提到了一点

1
2
3
4
5
6
def get_list():
    return [1,2,3,4,991,776,229,"aaa","str", 12.22]
 
def get_list1(index,end):
    a= get_list()
    return  a[index:end]

PySlice_New(从哪开始,到哪结束, 步进)

_Py_NoneStruct 参数表示留空

例如 l[2:] PySlice_New(2, _Py_NoneStruct,_Py_NoneStruct)

集合/字典

1
2
3
4
5
6
def test_set_dict():
    d = {1:'12',2:'4'}
    s = set([1,8,4,6])
 
    res = d.items(),d.values()
    return res, d,s[1:8]

字典初始化, 使用 PyDict_SetItem 函数, 第一个参数为字典的地址,第二个为key,第三个为值

集合初始化, 使用 PySet_Add 新增

字典的函数

items

values

在生成的源码里发现,有两种调用形式,大版本大于3和不大于3


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2025-2-28 18:58 被mingyuexc编辑 ,原因: 补充前言,编译pyd流程
上传的附件:
收藏
免费 15
支持
分享
最新回复 (10)
雪    币: 105
活跃值: (5096)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
6666666666666666
2025-2-11 02:52
0
雪    币: 4189
活跃值: (4547)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
先收藏,感谢分享。
2025-2-11 12:47
0
雪    币: 710
活跃值: (1268)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
pyd很难搞,先收藏了,以后慢慢学习
2025-2-13 10:40
0
雪    币: 225
活跃值: (443)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
能不能搞一个pyd的ida sig签名文件,这样没有符号也可以快速识别函数
2025-2-14 11:15
1
雪    币: 13015
活跃值: (4254)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
先收藏,感谢分享。 
2025-2-14 11:19
0
雪    币: 8588
活跃值: (5394)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
太强了 ,收藏点赞,精华
2025-2-14 15:10
0
雪    币: 239
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
太牛了师傅????
2025-2-15 09:56
0
雪    币: 769
活跃值: (2086)
能力值: ( LV7,RANK:105 )
在线值:
发帖
回帖
粉丝
9
rock 能不能搞一个pyd的ida sig签名文件,这样没有符号也可以快速识别函数

师傅好想法,但我测试了一下,没能成功用ida的flair工具生成sig。

最后于 2025-2-15 23:15 被mingyuexc编辑 ,原因:
2025-2-15 23:14
0
雪    币: 0
活跃值: (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
感谢分享,写的很牛,其实代码应该混淆,每个函数先调用主程序的加密数据进行验证,修改cython的编译算法, 几个步骤下来应该能提高pyd逆向的成本
2025-3-9 10:11
0
游客
登录 | 注册 方可回帖
返回