Skip to content

Instantly share code, notes, and snippets.

@BenGardiner
Last active September 15, 2017 13:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BenGardiner/25b77b7dc7463b6c3bf921c4ca57bcfe to your computer and use it in GitHub Desktop.
Save BenGardiner/25b77b7dc7463b6c3bf921c4ca57bcfe to your computer and use it in GitHub Desktop.
r2con `antir2` writeup

Writeup, from: https://github.com/JonathanBeverley , https://github.com/kensalter , https://github.com/BenGardiner

Notes:

  • Open challenge binary and analyze it
r2 -d antir2
[...]
[0x004008c0]> aaa
[ ] Analyze all flags starting with sym. and entry0 (aa)
[...]
  • When attempting to debug the program, there is a certain text string "r2 in debug.....hahahaha" printed before force-quitting you

  • I was able to cross reference the strings through a radare / search and then using axt find the point in which its mentioned.

[0x004008c0]> s str.r2_in_debug_mode_won_t_help_you_much__ha_ha_ha......_:__n
[0x004e1c67]> axt
data 0x421208 movabs rdi, str.r2_in_debug_mode_won_t_help_you_much__ha_ha_ha......_:__n in main
data 0x41f9e4 movabs rdi, str.r2_in_debug_mode_won_t_help_you_much__ha_ha_ha......_:__n in main
[0x004e1c67]> s 0x421208
  • It seems to be referenced from main; the anti-debug printout is called from a jump in main at 0x418fa6
[0x004e1c67]> axt
data 0x421208 movabs rdi, str.r2_in_debug_mode_won_t_help_you_much__ha_ha_ha......_:__n in main
data 0x41f9e4 movabs rdi, str.r2_in_debug_mode_won_t_help_you_much__ha_ha_ha......_:__n in main
[0x00000000]> s 0x421208
[0x00421208]> axt
code 0x418fa6 je 0x421208 in main
[0x00421208]> s 0x418fa6
  • which looks like a million jump statements... they all seem to reference loading [local_54h]
[0x00418fa6]> f antidebug_fromhere
[0x00418fa6]> pD 128 @ $$-64~..
│              ; JMP XREF from 0x00418f61 (main)
│           0x00418f66      8b45ac         mov eax, dword [local_54h]
│           0x00418f69      2dd355df15     sub eax, 0x15df55d3
│           0x00418f6e      898564ffffff   mov dword [local_9ch], eax
│       ┌─< 0x00418f74      0f8431150000   je 0x41a4ab
│      ┌──< 0x00418f7a      e900000000     jmp 0x418f7f
│      ││      ; JMP XREF from 0x00418f7a (main)
│      └──> 0x00418f7f      8b45ac         mov eax, dword [local_54h]
│       │   0x00418f82      2d6f9f2b19     sub eax, 0x192b9f6f
│       │   0x00418f87      898560ffffff   mov dword [local_a0h], eax
│      ┌──< 0x00418f8d      0f843c7a0000   je 0x4209cf
│     ┌───< 0x00418f93      e900000000     jmp 0x418f98
│     │││      ; JMP XREF from 0x00418f93 (main)
│     └───> 0x00418f98      8b45ac         mov eax, dword [local_54h]
│      ││   0x00418f9b      2d2f99231a     sub eax, 0x1a23992f
│      ││   0x00418fa0      89855cffffff   mov dword [local_a4h], eax
|     ┌───< ;-- antidebug_fromhere:
│     ┌───< 0x00418fa6      0f845c820000   je 0x421208
│    ┌────< 0x00418fac      e900000000     jmp 0x418fb1
│    ││││      ; JMP XREF from 0x00418fac (main)
│    └────> 0x00418fb1      8b45ac         mov eax, dword [local_54h]
│     │││   0x00418fb4      2dfa6b571d     sub eax, 0x1d576bfa
│     │││   0x00418fb9      898558ffffff   mov dword [local_a8h], eax
│    ┌────< 0x00418fbf      0f84cb140000   je 0x41a490
│   ┌─────< 0x00418fc5      e900000000     jmp 0x418fca
│   │││││      ; JMP XREF from 0x00418fc5 (main)
│   └─────> 0x00418fca      8b45ac         mov eax, dword [local_54h]
│    ││││   0x00418fcd      2df3fce31d     sub eax, 0x1de3fcf3
│    ││││   0x00418fd2      898554ffffff   mov dword [local_ach], eax
│   ┌─────< 0x00418fd8      0f84b7810000   je 0x421195
│  ┌──────< 0x00418fde      e900000000     jmp 0x418fe3
│  ││││││      ; JMP XREF from 0x00418fde (main)
│  └──────> 0x00418fe3      8b45ac         mov eax, dword [local_54h]
[0x00418fa6]> afvW~local_54h
 local_54h  0x416625,0x418de3,0x418df4,0x418e0a,0x418e20,0x418e36,0x418e4c,0x418e62,0x418e78,0x418e8e,0x418ea4,0x418eba,0x418ed0,0x418ee9,0x418f02,0x418f1b,0x418f34,0x418f4d,0x418f66,0x418f7f,0x418f98,0x418fb1,0x418fca,0x418fe3,0x418ffc,0x419015,0x41902e,0x419047,0x419060,0x419079,0x419092,0x4190ab,0x4190c4,0x4190dd,0x4190f6,0x41910f,0x4231a2
  • Inspecting around the function, all are reads, this local is only written to at 0x00418de3 with data from [local_50h].
[0x00418fa6]> pdb @ 0x00418dd8
│              ; JMP XREF from 0x00421239 (main)
│           0x00418dd8      8b45b0         mov eax, dword [local_50h]
│           0x00418ddb      89c1           mov ecx, eax
│           0x00418ddd      81e905e77080   sub ecx, 0x8070e705
│           0x00418de3      8945ac         mov dword [local_54h], eax
│           0x00418de6      894da8         mov dword [local_58h], ecx
│       ┌─< 0x00418de9      0f84e74d0000   je 0x41dbd6
  • Attempting to find the end, it looks like this whole function is cyclic. There are 33 jumpXREFs to the bottom. this might be some sort of.... loop? Switch statement?
[0x00418fa6]> pdf
[...]
│ ────────> 0x0042bdb5      c78568ffffff.  mov dword [local_98h], 0xd648722e
│ │││││││      ; XREFS: JMP 0x0042bdb0  JMP 0x00427b28  JMP 0x00426458  JMP 0x0042a251  JMP 0x00428b2b  JMP 0x0042bd62  JMP 0x0042aebc  JMP 0x00427265
│ │││││││      ; XREFS: JMP 0x00427b93  JMP 0x0042b9e0  JMP 0x0042bd92  JMP 0x004274e4  JMP 0x004276df  JMP 0x0042bda1  JMP 0x0042bce3  JMP 0x00427b0a
│ │││││││      ; XREFS: JMP 0x00427b51  JMP 0x0042aed9  JMP 0x0042bd48  JMP 0x0042bd19  JMP 0x0042b56b  JMP 0x00427bb3  JMP 0x00428f6b  JMP 0x0042b55c
│ │││││││      ; XREFS: JMP 0x00427bcd  JMP 0x00427b37  JMP 0x00429baa  JMP 0x00428f2d  JMP 0x00428f1e  JMP 0x0042aead  JMP 0x0042aef7  JMP 0x00427b6e
│ │││││││      ; XREFS: JMP 0x0042a094  JMP 0x00428f4d  JMP 0x0042bd7c  JMP 0x0042751e  JMP 0x0042a085  JMP 0x004274f3  JMP 0x00428f91  JMP 0x004260f0
│ │││││││      ; XREFS: JMP 0x00426467  JMP 0x0042b2f7  JMP 0x0042549c
│ └└└└└└└─< 0x0042bdbf      e9e391ffff     jmp 0x424fa7
│              ; JMP XREF from 0x0042bcf8 (main)
│ ────────> 0x0042bdc4      e867d20500     call fcn.00489030
│           0x0042bdc9      0f1f80000000.  nop dword [rax]
│           0x0042bdd0      b8061d4e00     mov eax, str.aes_partial_   ; 0x4e1d06 ; "aes(partial)"
└           0x0042bdd5      c3             ret
  • How does it know it is being debugged? The message only plays when the local_54h is equal to 1A23992F.
[0x00418fa6]> pdb @ 0x00418fa6
│              ; JMP XREF from 0x00418f93 (main)
│           0x00418f98      8b45ac         mov eax, dword [local_54h]
│           0x00418f9b      2d2f99231a     sub eax, 0x1a23992f
│           0x00418fa0      89855cffffff   mov dword [local_a4h], eax
|       ┌─< ;-- antidebug_fromhere:
│       ┌─< 0x00418fa6      0f845c820000   je 0x421208
  • The magic value 0x1a23992f shows up only three times; the last is not in code, the first is the test against that value. Let's look at the second
[0x00418fa6]> /v 0x1a23992f
Searching 4 bytes in [0x400000-0x522000]
hits: 3
0x00418f9c hit1_0 2f99231a
0x0041ebbd hit1_1 2f99231a
0x0041fa03 hit1_2 2f99231a
[0x00418fa6]> pd @ hit1_1-5
│       ┌─< 0x0041ebb8      7d26           jge 0x41ebe0
│       │   0x0041ebba      0000           add byte [rax], al
│       │      ; JMP XREF from 0x00418f5b (main)
│       │   0x0041ebbc  ~   b82f99231a     mov eax, 0x1a23992f
|;-- hit1_1:
│       │   0x0041ebbd      2f             invalid                     ; 0x1a23992f
│       │   0x0041ebbe      99             cdq
│       │   0x0041ebbf      231a           and ebx, dword [rdx]
[...]

NB: the flag on the immeadiate is breaking the disassembly there, we'll remove flags in the following to avoid this.

  • that value, once loaded into eax makes its way magically to local_54h (the EBB is very very long)

  • the above is only called is local_54h is equal to 0xae2d291

[0x004008c0]> s 0x00418f5b
[0x00418f5b]> pd
[0x00418f5b]> pdb
│              ; JMP XREF from 0x00418f48 (main)
│           0x00418f4d      8b45ac         mov eax, dword [local_54h]
│           0x00418f50      2d91d2e20a     sub eax, 0xae2d291
│           0x00418f55      898568ffffff   mov dword [local_98h], eax
│       ┌─< 0x00418f5b      0f845b5c0000   je 0x41ebbc
  • which is called only if local_54h is not 0x94524fa
│       │      ; JMP XREF from 0x00418f2f (main)
│       └─> 0x00418f34      8b45ac         mov eax, dword [local_54h]
│           0x00418f37      2dfa244509     sub eax, 0x94524fa
│           0x00418f3c      89856cffffff   mov dword [local_94h], eax
│       ┌─< 0x00418f42      0f84e2810000   je 0x42112a                 ;[2]
│      ┌──< 0x00418f48      e900000000     jmp 0x418f4d                ;[3]
  • and so on, testing for various other values of local_54h that it is not. We'll focus on the test for the concrete value 0xae2d291

  • the value 0xae2d291 which local_54h must attain is written to local_50h when local_34h is 6

[0x0041eba7]> /v 0xae2d291
Searching 4 bytes in [0x400000-0x522000]
hits: 2
0x00418f51 hit3_0 91d2e20a
0x0041eba7 hit3_1 91d2e20a
[0x0041eba7]> s 0x0041eba7
[0x0041eba7]> f-hit*
[0x0041eba7]> pdb
│              ; JMP XREF from 0x00418eaf (main)
│           0x0041eba1      b82f82de24     mov eax, 0x24de822f
│           0x0041eba6      b991d2e20a     mov ecx, 0xae2d291
│           0x0041ebab      8b55cc         mov edx, dword [local_34h]
│           0x0041ebae      83fa06         cmp edx, 6                  ; 6
│           0x0041ebb1      0f45c1         cmovne eax, ecx
│           0x0041ebb4      8945b0         mov dword [local_50h], eax
│       ┌─< 0x0041ebb7      e97d260000     jmp 0x421239
  • it's not clear how that would also propagate to local_54h -- but let's just roll with it. Assuming it will, then if we prevent the magic value 0xae2d291 from getting into local_50h, we will prevent detection of debugging. So we can patch-out the conditional mov, cmovne at 0x41ebb1
[0x0041eba7]> s 0x0041ebb1
[0x0041ebb1]> "wa nop;nop;nop"
Written 3 bytes (nop;nop;nop) = wx 909090
[0x0041ebb1]> pdb
│              ; JMP XREF from 0x00418eaf (main)
│           0x0041eba1      b82f82de24     mov eax, 0x24de822f
│           0x0041eba6      b991d2e20a     mov ecx, 0xae2d291
│           0x0041ebab      8b55cc         mov edx, dword [local_34h]
│           0x0041ebae      83fa06         cmp edx, 6                  ; 6
│           0x0041ebb1      90             nop
│           0x0041ebb2      90             nop
│           0x0041ebb3      90             nop
│           0x0041ebb4      8945b0         mov dword [local_50h], eax
│       ┌─< 0x0041ebb7      e97d260000     jmp 0x421239
[0x0041ebb1]>
  • yay! we patched-out the anti-debug check!
[0x0041ebb1]> dc
child stopped with signal 28
[+] SIGNAL 28 errno=0 addr=0x00000000 code=128 ret=0
got signal...
[0x004008c0]> dc
*******************************************
* Radare2con 2017 rhme3 pre-quals edition *
*******************************************

r<< Can you r2 me?

Plaintext : 47 65 74 20 74 68 65 20 61 65 73 6B 65 79 21 21
Encrypted : FD DA 9B 78 FC F8 E9 BF 33 72 6E 0A 8A E5 F6 8C
Decrypted : 47 65 74 20 74 68 65 20 61 65 73 6B 65 79 21 21
[0x00484b88]>
  • Let's restart that debug session and plan a breakpoint. Working backwards from the "Decrypted" string
[0x0041ebb1]> s str.Decrypted
[0x004e1bc9]> axt
data 0x400c97 mov eax, str.Decrypted in main
[0x004e1bc9]> s 0x400c97
[0x00400c97]> pdb
[...]
│           0x00400c34      e857c10200     call fcn.0042cd90
│           0x00400c39      b8a01b4e00     mov eax, 0x4e1ba0
│           0x00400c3e      89c7           mov edi, eax
│           0x00400c40      8b8564fdffff   mov eax, dword [local_29ch]
│           0x00400c46      4188c3         mov r11b, al
│           0x00400c49      4488d8         mov al, r11b
│           0x00400c4c      e8bfad0400     call fcn.0044ba10
│           0x00400c51      41b9b51b4e00   mov r9d, str.Plaintext      ; 0x4e1bb5 ; "Plaintext"
│           0x00400c57      4489cf         mov edi, r9d
│           0x00400c5a      41b9901b4e00   mov r9d, 0x4e1b90
│           0x00400c60      4489ce         mov esi, r9d
│           0x00400c63      41b910000000   mov r9d, 0x10               ; 16
│           0x00400c69      4489ca         mov edx, r9d
│           0x00400c6c      898550fdffff   mov dword [local_2b0h], eax
│           0x00400c72      44898d4cfdff.  mov dword [local_2b4h], r9d
│           0x00400c79      e8c20a0100     call 0x411740
│           0x00400c7e      b8bf1b4e00     mov eax, str.Encrypted      ; 0x4e1bbf ; "Encrypted"
│           0x00400c83      89c7           mov edi, eax
│           0x00400c85      488bb568fdff.  mov rsi, qword [local_298h]
│           0x00400c8c      8b954cfdffff   mov edx, dword [local_2b4h]
│           0x00400c92      e8a90a0100     call 0x411740
│           0x00400c97      b8c91b4e00     mov eax, str.Decrypted      ; 0x4e1bc9 ; "Decrypted"
│           0x00400c9c      89c7           mov edi, eax
│           0x00400c9e      488bb558fdff.  mov rsi, qword [local_2a8h]
│           0x00400ca5      8b954cfdffff   mov edx, dword [local_2b4h]
│           0x00400cab      e8900a0100     call 0x411740
│           0x00400cb0      64488b0c2528.  mov rcx, qword fs:[0x28]    ; [0x28:8]=-1 ; '(' ; 40
│           0x00400cb9      488b75f8       mov rsi, qword [local_8h]
│           0x00400cbd      4839f1         cmp rcx, rsi
│       ┌─< 0x00400cc0      0f8510000000   jne 0x400cd6
  • The first call to 0x411740 seems like a good spot.
[0x00400c97]> db 0x00400c79
[0x00400c97]> dc
child stopped with signal 28
[+] SIGNAL 28 errno=0 addr=0x00000000 code=128 ret=0
got signal...
[0x004008c0]> dc
*******************************************
* Radare2con 2017 rhme3 pre-quals edition *
*******************************************

r<< Can you r2 me?

hit breakpoint at: 400c79
[0x00400c79]>
  • Let's check the stack
[0x00400c79]> ad 10 @rsp
0x7fff1ecc6bb0  0000000000000000  (null)
0x7fff1ecc6bb8  0000000010000000  pointer  0x1000000000
`- 0x1000000000  ffffffffffffffff  invalid
0x7fff1ecc6bc0  1400000000000000  pointer  0x00000014
`- 0x00000014  ffffffffffffffff  invalid
0x7fff1ecc6bc8  206ecc1eff7f0000  pointer  0x7fff1ecc6e20
`- 0x7fff1ecc6e20  4765742074686520  pointer  0x2065687420746547
`- 0x7fff1ecc6bd0  0000000000000000  (null)
0x7fff1ecc6bd8  306ecc1eff7f0000  pointer  0x7fff1ecc6e30
`- 0x7fff1ecc6e30  fdda9b78fcf8e9bf  pointer  0xbfe9f8fc789bdafd
`- 0x7fff1ecc6be0  306ccc1eff7f0000  pointer  0x7fff1ecc6c30
`- 0x7fff1ecc6c30  7ccdaca5e94484fb  pointer  0xfb8444e9a5accd7c
`- 0x7fff1ecc6be8  4500000000000000  pointer  0x00000045
`- 0x00000045  ffffffffffffffff  invalid
0x7fff1ecc6bf0  00000000a9085105  pointer  0x55108a900000000
`- 0x55108a900000000  ffffffffffffffff  invalid
0x7fff1ecc6bf8  0000000086aa782f  pointer  0x2f78aa8600000000
`- 0x2f78aa8600000000  ffffffffffffffff  invalid
  • we recognize 4765742074686520 as the plaintext. I wonder what is around there?
[0x00400c79]> px @ 0x7fff1ecc6e20
- offset -       0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x7fff1ecc6e20  4765 7420 7468 6520 6165 736b 6579 2121  Get the aeskey!!
0x7fff1ecc6e30  fdda 9b78 fcf8 e9bf 3372 6e0a 8ae5 f68c  ...x....3rn.....
0x7fff1ecc6e40  fdda 9b78 fcf8 e9bf 3372 6e0a 8ae5 f68c  ...x....3rn.....
0x7fff1ecc6e50  7261 6461 7265 3263 6f6e 3465 7665 7221  radare2con4ever!
0x7fff1ecc6e60  60db 4300 0000 0000 003f 3c3c d183 316e  `.C......?<<..1n
0x7fff1ecc6e70  1820 7200 0000 0000 46d2 4300 0000 0000  . r.....F.C.....
0x7fff1ecc6e80  0000 0000 0000 0000 0000 0000 0100 0000  ................
0x7fff1ecc6e90  b86f cc1e ff7f 0000 e009 4000 0000 0000  .o........@.....
0x7fff1ecc6ea0  b802 4000 0000 0000 4f84 4b96 1557 d8fe  ..@.....O.K..W..
0x7fff1ecc6eb0  60db 4300 0000 0000 f0db 4300 0000 0000  `.C.......C.....
0x7fff1ecc6ec0  0000 0000 0000 0000 0000 0000 0000 0000  ................
0x7fff1ecc6ed0  4f84 7b0b 696a 2601 4f84 7972 7657 d8fe  O.{.ij&.O.yrvW..
0x7fff1ecc6ee0  0000 0000 0000 0000 0000 0000 0000 0000  ................
0x7fff1ecc6ef0  0000 0000 0000 0000 0000 0000 0000 0000  ................
0x7fff1ecc6f00  0000 0000 0000 0000 0000 0000 0000 0000  ................
0x7fff1ecc6f10  bb07 0000 0000 0000 b86f cc1e ff7f 0000  .........o......
  • EYYYYYYYYYYYYYYYYYYYYYYYY hfound it.
$echo -n 'Get the aeskey!!' | openssl aes-128-ecb -e -nopad -nosalt -K $(echo -n 'radare2con4ever!' | xxd -ps) | xxd -u -g1
00000000: FD DA 9B 78 FC F8 E9 BF 33 72 6E 0A 8A E5 F6 8C  ...x....3rn.....
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment