您的位置:首页 > 房产 > 建筑 > 签了外包合同被辞退有补偿吗_视频网站数据库设计_目前最牛的二级分销模式_重庆森林经典台词截图

签了外包合同被辞退有补偿吗_视频网站数据库设计_目前最牛的二级分销模式_重庆森林经典台词截图

2025/2/24 22:01:29 来源:https://blog.csdn.net/jmm18363027827/article/details/145043001  浏览:    关键词:签了外包合同被辞退有补偿吗_视频网站数据库设计_目前最牛的二级分销模式_重庆森林经典台词截图
签了外包合同被辞退有补偿吗_视频网站数据库设计_目前最牛的二级分销模式_重庆森林经典台词截图

浅析代码重定位技术

前言

大家好,我是科锐49期远程班的一名学员。此篇文章是我消化上课内容后写的一篇教学向文章如有理解错误的地方恳请各位前辈斧正,学习任务繁重,所以文章更新较慢请各位谅解。
我将尽量用简单易懂的语言阐述清楚该技术要点,并且辅以相关代码示例帮助新手小白更好的理解。

0x00 大纲

  1. 什么是代码重定位?
  2. 为什么我们需要它?(应用场景)
  3. 重定位实现方法一(段首地址法)
  4. 重定位实现方法二(段偏移法)
  5. 结语
  6. 参考

环境: Windows11 23H2

编译器: ml.exe

链接器: link.exe

适用语言: 32位汇编

0x01 什么是代码重定位?

代码重定位 代码重定位技术是指在程序执行的过程中,操作系统或加载器将程序中的地址引用调整到实际加载时的内存地址的过程, 它允许我们在不同的程序中正确的执行一个片段的代码而不用考虑在当前代码中的实际加载偏移,换句话讲地址无关(Position-Independent Code, PIC)技术的实现就是基于代码重定位来进行实现的。

0x02 代码重定位的应用场景

我们考虑如下问题,当前存在一个进程A,他需要在注入进程B之后立马执行一段自己的代码且这段代码中包含地址相关的指令比如某变量的读写。这时我们采用远程线程注入的形式利用APICreateRemoteThread VirtualAllocEx WriteProcessMemory将要执行的汇编代码注入到目标进程中。

首先我们先给出这段代码的汇编实现

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

; 2024.11.24 writed by fake77

; kanxue: https://bbs.kanxue.com/homepage-983513.htm

.686

.model flat, stdcall

option casemap:NONE

include windows.inc

include user32.inc

include kernel32.inc

includelib user32.lib

includelib kernel32.lib

WinMain proto :DWORD, :DWORD, :DWORD, :DWORD

.data?

  hInstance HINSTANCE ?

  CommandLine LPSTR ?

.data

  g_szTargetProcessName db "鎵浄", 0

  g_szCaption db "Err", 0

  g_szErr1 db "Err 1", 0

  g_szErr2 db "Err 2", 0

  g_szErr3 db "Err 3", 0

  g_szErr4 db "Err 4", 0

  g_szErr5 db "Err 5", 0

  g_szErr6 db "Err 6", 0

   

.code

INJECT_BEGIN:

  ; todo inject code

  ; inject data area

CODE_BEGIN:

  ; inject asm code area

CODE_END:

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD

  ; alloc local var

  LOCAL hWnd:HWND ; handle of window

  LOCAL dwPid:DWORD ; process id for open process

  LOCAL hProc:DWORD ; process handle

  LOCAL pAddr:LPVOID ; target mem pointer

  LOCAL dwWrited:DWORD; writed byte num by WriteProcessMemory

   

  ; 1. get window handle

  invoke FindWindow, NULL, offset g_szTargetProcessName

  mov hWnd, eax

  .IF !eax

     invoke MessageBox, NULL, offset g_szErr1, offset g_szCaption, MB_OK

  .ENDIF

   

  ; 2. find process

  invoke GetWindowThreadProcessId, hWnd, addr dwPid

  .IF !eax

     invoke MessageBox, NULL, offset g_szErr2, offset g_szCaption, MB_OK

  .ENDIF

  ; 3. get process handle

  invoke OpenProcess, PROCESS_ALL_ACCESS, FALSE, dwPid

  mov hProc, eax

  .IF !eax

     invoke MessageBox, NULL, offset g_szErr3, offset g_szCaption, MB_OK

  .ENDIF

  ; 4. alloc mem in target process and prvg set read write

  invoke VirtualAllocEx, hProc, NULL, 1000h, MEM_COMMIT, PAGE_EXECUTE_READWRITE

  mov pAddr, eax

  .IF !eax

     invoke MessageBox, NULL, offset g_szErr4, offset g_szCaption, MB_OK

  .ENDIF

  ; 5. write code to target process

  invoke WriteProcessMemory, hProc, pAddr, offset INJECT_BEGIN, \

  offset CODE_END - offset INJECT_BEGIN, addr dwWrited

  .IF !eax

     invoke MessageBox, NULL, offset g_szErr5, offset g_szCaption, MB_OK

  .ENDIF

   

  ; 6. create remote thread to run code

  mov eax, pAddr

  add eax, offset CODE_BEGIN - offset INJECT_BEGIN ; code entry

  invoke CreateRemoteThread, hProc, NULL, 0, eax, NULL, 0, NULL

    .IF !eax

     invoke MessageBox, NULL, offset g_szErr6, offset g_szCaption, MB_OK

  .ENDIF

   

  ; makesure stack banlance

  ret 10

WinMain endp

start:

  invoke GetModuleHandle, NULL

    mov    hInstance,eax

     

    invoke GetCommandLine

    mov    CommandLine,eax

     

    invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT

    invoke ExitProcess,eax

end start

我们尝试进行注入如下代码,我们希望在目标进程中弹出一个框

1

2

3

4

5

6

7

8

INJECT_BEGIN:

    g_szText db "扫雷", 0

    g_szCaption db "u got inject", 0

    g_pfnMsgBox dd 0

CODE_BEGIN:

    invoke MessageBoxA, NULL, offset g_szText, offset g_szCaption, MB_OK

    ret 4 ; stdcall 平栈

CODE_END:

我们直接用两个x64dbg进行调试

这里已经成功将要执行的代码注入到了目标进程中

我们尝试直接运行看看会发生什么?

可以看到我们这里在执行之后出现了C05这是在我们的意料之中的因为在这里不仅仅是MessageBoxA,整个代码片段都是地址强相关一切的偏移都是在原有进程的偏移所以在新的进程无法使用。

所以在这里我们需要通过地址重定位技术让代码段脱离地址依赖能够自己获取偏移以便于成功运行。

下面我将给出两种重定位技术

  1. 段首地址法
  2. 段偏移法

0x03 段首地址法

为什么叫段首地址法这个词很形象的描述了这种方法,当我们在编译汇编程序的时候我们能够确定的并且控制的东西是从地址标签INJECT_BEGINCODE_BEGIN中的各种变量偏移,不能控制的是加载的地址,但是如果我们能够获取到 INJECT_BEGIN的地址则可以根据已知的偏移获取到正确的代码偏移量。

到此自身代码的偏移问题已经可以解决,现在我们还需要解决调用系统API的时候在不同的进程中API加载的地址也是不同的问题,那么这个问题如何解决呢?

对于这个问题我们应该利用系统自身带的PIC API去进行定位,看过我写的文章的小伙伴应该已经知道了,没错就是LoadLibraryGetProcAddress这两个API是系统自带的PIC API, 他们通常在不同进程中的地址是相同的,我们通过这个API将MessageBoxA的地址加载到要注入的地址中去。

tips对于32位汇编我们不能直接拿到IP寄存器的值我们需要通过call命令将返回地址压入栈中然后利用pop手动获取到IP的值,对于地址重定向中我们获取到当前执行的命令的IP值则可以通过如下代码段

1

2

3

4

5

6

call $ + 5 ; 这里值得注意的是 + 5 是因为call指令的长度是5个字节

           ; 它的字节码为 E8 00 00 00 00

           ; 而 $ 符则是在编译器获取当前指令的地址而 + 5是因为

           ; call 和 jmp一样都是获取的下一条指令的IP当我们call

           ; $ + 5的时候就可以直接获取到当前 pop eax这条指令的地址

pop eax

基于如上原理我们给出如下实现

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

.code

INJECT_BEGIN:  

    g_szText db "扫雷", 0  

    g_szRemoteCaption db "u got inject", 0 

    g_pfnMsgBox dd 0 ; MessageBoxA指针

CODE_BEGIN: 

     call $+5

     pop ebx ;获取当前指令地址

     sub ebx, (offset CODE_BEGIN - offset INJECT_BEGIN) + 5 ; 获取到段首的偏移

      

     push MB_OK

      

     mov eax, offset g_szText - offset INJECT_BEGIN ; 获取g_szText到段首的偏移

     add eax, ebx

     push eax

      

     mov eax, offset g_szRemoteCaption - offset INJECT_BEGIN ; 获取g_szRemoteCaption到段首的偏移

     add eax, ebx

     push ebx

      

     push NULL

      

     mov eax, offset g_pfnMsgBox - offset INJECT_BEGIN

     add eax, ebx

     call dword ptr [eax] ; 通过指针调用

      

     ; invoke MessageBoxA, NULL, offset g_szText, offset g_szRemoteCaption, MB_OK   

      

     ret 4 ; stdcall 平栈CODE_END:

CODE_END:

MessageBox地址获取实现

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

; WinMain....

; 因为是代码段所以要更改下权限

 invoke VirtualProtect,offset INJECT_BEGIN, 1000h, PAGE_EXECUTE_READWRITE, addr dwOld

   ; check ...

 ; 获取user32的地址

 invoke LoadLibrary, offset g_user32

   ; check ...

 mov hUser32, eax

 ; 获取到MessageBoxA的地址

 invoke GetProcAddress, hUser32, g_message

   ; check ...

 mov g_pfnMsgBox, eax

 ; 还原权限

 invoke VirtualProtect,offset INJECT_BEGIN, 1000h, dwOld, addr dwOld

  ; check ...

  

 ; WinMain....

我们通过调试来观察下过程

成功定位到代码段

成功运行! 至此就是段首地址法的内容

下面我们进入段偏移法的讲解

0x04 段偏移法

段偏移法段首地址法的最大区别就是段偏移法是通过计算加载到目标进程的地址和原进程地址的偏移,通过原进程地址 + 偏移 = 目标进程的地址的方式重定位代码段

给出如下实现

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

.code

INJECT_BEGIN:  

    g_szText db "扫雷", 0  

    g_szRemoteCaption db "u got inject", 0 

    g_pfnMsgBox dd 0 ; MessageBoxA指针

CODE_BEGIN: 

     call $+5

NEXT:

     pop ebx ;获取当前指令地址

     ; sub ebx, (offset CODE_BEGIN - offset INJECT_BEGIN) + 5 ; 获取到段首的偏移

      

     sub ebx, offset NEXT ; NEXT是在编译其确定的地址而ebx则是运行时确定的其差值就是偏移值.

      

     push MB_OK

      

     ;mov eax, offset g_szRemoteCaption - offset INJECT_BEGIN ; 获取g_szRemoteCaption到段首的偏移

     mov eax, offset g_szText

     add eax, ebx

     push eax

      

      

     ;mov eax, offset g_szText - offset INJECT_BEGIN ; 获取g_szText到段首的偏移

     mov eax, offset g_szRemoteCaption

     add eax, ebx

     push eax

      

     push NULL

      

     ; mov eax, offset g_pfnMsgBox - offset INJECT_BEGIN

     mov eax, offset g_pfnMsgBox

     add eax, ebx

     call dword ptr [eax] ; 通过指针调用

      

     ; invoke MessageBoxA, NULL, offset g_szText, offset g_szRemoteCaption, MB_OK   

      

     ret 4 ; stdcall 平栈CODE_END:

CODE_END:

成功重定位到代码段

成功运行

0x05 结语

代码重定位技术在许多计算机科学和软件工程领域中扮演着重要角色,尤其是在注入技术、动态链接库(DLL)、以及操作系统内存管理等方面。掌握代码重定位技术不仅有助于理解这些领域的基础概念,还能为开发和安全研究提供强大的支持。

0x06 参考

  1. MSDN
  2. 结语0x01为ChatGpt编写(理论性的东西实在不想动手写)

PS

欢迎大家在评论区讨论。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com