Ilya_konstantinov

Untitled

Feb 27th, 2026 (edited)
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.13 KB | None | 0 0
  1. ======================== solution.S
  2. .intel_syntax noprefix
  3. .section .note.GNU-stack
  4.  
  5. .text
  6. # uint64_t Indirect.Call(
  7. # uint64_t (*rax)(uint64_t, uint64_t),
  8. # uint64_t (*rbx)(),
  9. # uint64_t (*rcx)()
  10. # );
  11. .global Indirect.Call
  12. Indirect.Call:
  13. // TODO: your code here.
  14. ret
  15.  
  16.  
  17. ======================== test.cpp
  18. #include <iostream>
  19. #include <cstdint>
  20. #include <cassert>
  21.  
  22. extern uint64_t (*realH)();
  23. extern uint64_t (*realG)();
  24.  
  25. extern "C" uint64_t GWrapper();
  26. extern "C" uint64_t HWrapper();
  27. extern "C" uint64_t IndirectCallWrapper(uint64_t (*f)(uint64_t, uint64_t),
  28. uint64_t (*g)(), uint64_t (*h)());
  29.  
  30. extern "C" uint64_t ReadRSP();
  31. extern "C" uint64_t ReadRSP2(uint64_t, uint64_t);
  32. asm(R"(
  33. ReadRSP:
  34. ReadRSP2:
  35. mov rax, rsp
  36. ret
  37. )");
  38.  
  39. int main() {
  40. {
  41. realG = []() -> uint64_t { return 456; };
  42. realH = []() -> uint64_t { return 123; };
  43.  
  44. uint64_t result = IndirectCallWrapper(
  45. [](uint64_t a, uint64_t b) { return a + b; }, GWrapper, HWrapper);
  46.  
  47. assert(result == 123 + 456);
  48.  
  49. result = IndirectCallWrapper([](uint64_t a, uint64_t b) { return a & ~b; },
  50. HWrapper, GWrapper);
  51. assert(result == (123 & ~456));
  52. }
  53.  
  54. {
  55. uint64_t result1 = IndirectCallWrapper(
  56. [](uint64_t a, uint64_t b) { return ((a & 15) << 4) | (b & 15); },
  57. ReadRSP, ReadRSP);
  58.  
  59. {
  60. assert(result1 == (128 | 8) && "Stack of g or h is not aligned");
  61. }
  62.  
  63. uint64_t result2 = IndirectCallWrapper(
  64. ReadRSP2, []() -> uint64_t { return 0; },
  65. []() -> uint64_t { return 456; });
  66. {
  67. assert((result2 & 15) == 8 && "Stack of f is not aligned");
  68. }
  69. }
  70.  
  71. {
  72. constexpr uint64_t kValue1 = 0x0123456789ABCDEFull;
  73. constexpr uint64_t kValue2 = 0xF543861BECD7A209ull;
  74.  
  75. uint64_t result =
  76. IndirectCallWrapper([](uint64_t a, uint64_t b) { return ~a & b; },
  77. []() { return kValue1; }, []() { return kValue2; });
  78.  
  79. assert(result == (~kValue1 & kValue2));
  80. }
  81. std::cout << "All test passed.";
  82. }
  83. ======================== wrapper.S
  84. .intel_syntax noprefix
  85.  
  86. .section .note.GNU-stack
  87.  
  88. .section .rodata, "a", @progbits
  89.  
  90. fmt:
  91. .asciz "Register %s was not preserved"
  92.  
  93. #define REG_STR(reg) \
  94. s##reg: \
  95. .asciz #reg
  96.  
  97. REG_STR(rax)
  98. REG_STR(rbx)
  99. REG_STR(rcx)
  100. REG_STR(rdx)
  101. REG_STR(rdi)
  102. REG_STR(rsi)
  103. REG_STR(rbp)
  104. REG_STR(r8)
  105. REG_STR(r9)
  106. REG_STR(r10)
  107. REG_STR(r11)
  108. REG_STR(r12)
  109. REG_STR(r13)
  110. REG_STR(r14)
  111. REG_STR(r15)
  112.  
  113. #undef REG_STR
  114.  
  115. .bss
  116. .global realG
  117. realG:
  118. .quad 0
  119. .global realH
  120. realH:
  121. .quad 0
  122.  
  123. .macro Clobber
  124. mov rax, 123
  125. mov rcx, 124
  126. mov rdx, 125
  127. mov rsi, 126
  128. mov rdi, 127
  129. mov r8, 128
  130. mov r9, 129
  131. mov r10, 130
  132. mov r11, 131
  133. .endm
  134.  
  135. .text
  136. .global GWrapper
  137. GWrapper:
  138. Clobber
  139. jmp [rip + realG]
  140.  
  141. .global HWrapper
  142. HWrapper:
  143. Clobber
  144. jmp [rip + realH]
  145.  
  146. .global IndirectCallWrapper
  147. IndirectCallWrapper:
  148. push rbx
  149.  
  150. mov rbx, rsi
  151. mov rcx, rdx
  152. mov rax, rdi
  153.  
  154. push rbx
  155. push rcx
  156. push rdx
  157. push rdi
  158. push rsi
  159. push rbp
  160. push r8
  161. push r9
  162. push r10
  163. push r12
  164. push r13
  165. push r14
  166. push r15
  167. push r11
  168.  
  169. call Indirect.Call
  170.  
  171. cmp r11, [rsp]
  172. jne .r11_mismatch
  173. add rsp, 8
  174.  
  175. .macro CHECK_REG reg
  176. cmp \reg, [rsp]
  177. lea r11, [rip + s\reg]
  178. jne .mismatch
  179. add rsp, 8
  180. .endm
  181.  
  182. CHECK_REG r15
  183. CHECK_REG r14
  184. CHECK_REG r13
  185. CHECK_REG r12
  186. CHECK_REG r10
  187. CHECK_REG r9
  188. CHECK_REG r8
  189. CHECK_REG rbp
  190. CHECK_REG rsi
  191. CHECK_REG rdi
  192. CHECK_REG rdx
  193. CHECK_REG rcx
  194. CHECK_REG rbx
  195.  
  196. pop rbx
  197. ret
  198.  
  199. .r11_mismatch:
  200. lea rdi, [rip + fmt]
  201. lea rsi, [rip + sr11]
  202. xor eax, eax
  203. call printf
  204. call abort
  205.  
  206. .mismatch:
  207. lea rdi, [rip + fmt]
  208. mov rsi, r11
  209. and rsp, -16
  210. xor eax, eax
  211. call printf
  212. call abort
  213.  
Advertisement
Add Comment
Please, Sign In to add comment