0% found this document useful (0 votes)
22 views78 pages

Codebreaker3 Techtalk v6-1

The Codebreaker Challenge 3.0 involves reverse-engineering software used by a terrorist organization for secret communication. Participants must complete four progressively difficult tasks, including executing hidden functionalities, bypassing authentication, creating an encoder, and spoofing messages. Resources and instructions for the challenge can be found online, and successful completion leads to a message from the NSA encouraging further engagement with their career opportunities.

Uploaded by

Joe Ordinary
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views78 pages

Codebreaker3 Techtalk v6-1

The Codebreaker Challenge 3.0 involves reverse-engineering software used by a terrorist organization for secret communication. Participants must complete four progressively difficult tasks, including executing hidden functionalities, bypassing authentication, creating an encoder, and spoofing messages. Resources and instructions for the challenge can be found online, and successful completion leads to a message from the NSA encouraging further engagement with their career opportunities.

Uploaded by

Joe Ordinary
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Fall 2015

CODEBREAKER CHALLENGE 3.0


1
Challenge Scenario
NSA has discovered that the leadership of a
terrorist organization is using a new method of
communicating secret messages to its
operatives in the field and has provided each
individual with a unique program for decoding
messages. Your mission is to reverse-engineer
this software and develop capabilities to exploit
the secret messaging component.

2
The Challenge

 There are 4 different levels or "tasks" to this


challenge problem
 Task 1: Determine how to execute the hidden
functionality
 Task 2: Bypass an authentication check
 Task 3: Create an encoder program
 Task 4: Spoof a message to a high-value target
 Each task gets progressively harder and
builds off previous ones
3
The Challenge (cont.)

 Challenge materials and instructions can be


found at [Link]

 Register for an account with your .edu email


address

4
Reverse Engineering Tips

 Examine strings in the binary using IDA


 Look for clues that relate to the functionality you are trying
to find / reverse
 Utilize IDA xrefs to find code that references the string(s) of
interest
 Utilize symbols (e.g., function names) to help determine
what a section of code does
 Try setting debugger breakpoints to help RE code
 Single-step after hitting a breakpoint and see how the
values in registers/memory change
 Look for the result of interesting computations. You can
sometimes get the data you need from memory
 Leverage online resources, e.g.,Intel manuals, RE
lectures, etc. for help on reverse-engineering
5
Technical Walkthrough

 2014 Codebreaker Challenge on Windows


using IDA Pro Demo

 This binary can be downloaded from


[Link]

6
Running the program

7
Running the program (2)

8
Disassemble

 Disassemble the Codebreaker2 binary


 If asked whether you want to use Proximity View
 Click no
 Use graph view

9
Disassemble (2)

10
Disassemble (3)

11
Observe Strings
 Observe the strings that show up in IDA
 Click Views->Open Subviews->Strings
 You should see the strings that are displayed when
you run the program
Yahoo! Weather forecast for

Full forecast available at:

Weatherman version 6.8.1

12
Observe Strings (2)

13
Observe Strings (3)

14
Observe Strings (4)

15
C:\\tmp\\secrets

 Double click on the “C:\\tmp\\secrets” string


 This takes you to the data section of the binary
where the string is stored
 To the right of the string are cross references
to this address (show up as DATA XREF in
IDA)
 Press ctrl-x to pull up a cross-references
window; you will see two different references

16
C:\\tmp\\secrets (2)

17
C:\\tmp\\secrets (3)

18
Double-click Reference

 You should now be looking at disassembled


x86 code
 We just leveraged the fact that in order to use
“C:\\tmp\\secrets” in the program, the code had to
reference the address in the data section of the
program where the string was stored.
 Using xrefs in IDA is a quick and easy way to
find interesting code sections

19
Double-click Reference (2)

20
Explore Code Block

21
Explore Code Block (2)

22
Explore Code Block (3)

23
Running the program (for real)

24
Explore Code Block (4)

25
Explore Code Block (5)

26
Running the program (for real)(2)

27
Tier 1 Complete!

 Pretty straight forward


 Just looking at the strings may have been
enough to get you through this

 … on to Tier 2!

28
Running the program (for real)(2)

29
Explore Code Block (6)

30
Explore Code Block (7)

31
Explore Code Block (8)

32
Explore Code Block (9)

33
getPasswordFromUsername

34
What does this code do?
mov edx, 0xAC769185 // edx = 0xAC769185
mov eax, ecx // ecx = input value
imul edx // edx:eax = eax * edx
lea eax, [edx + ecx*0x1] // eax = edx + ecx
mov edx, eax // edx = eax
sar edx, 0x6 // arith right shift; edx = edx >> 0x6
mov eax, ecx // eax = ecx
sar eax, 0x1f // eax = eax >> 0x1f (31)
mov ebx, edx // ebx = edx
sub ebx, eax // ebx = ebx - eax
mov eax, ebx // eax = ebx
imul eax, eax, 0x5f // edx:eax = eax * 0x5f (95)
mov edx, ecx // edx = ecx
sub edx, eax // edx = edx – eax
// edx is the final result

35
Signed Division and Remainder

 The code computes: edx = ecx % 95


 Why multiply by 0xAC769185 and where did that
number come from?
 Division is a time consuming operation
 When the divisor is a constant, the compiler can
optimize the computation
 The basic trick is to multiply by a “magic value”
(~ 232/d) and extract the leftmost 32 bits of the
product
 The following site computes these numbers for
you: [Link]
36
getPasswordFromUsername (2)

37
Running the program (3)

38
Running the program (4)

39
Tier 2 Complete!

 Required either reverse engineering the


password derivation function or just using a
debugger to see the computed value

 … on to Tier 3!

40
Running the program (4)

41
Running the program (5)

42
Running the program (6)

43
Explore Code Block (10)

44
Inside encrypt (1)

45
Inside encrypt (2)

46
SHA256 Functions

47
Inside encrypt (3)

48
Initial computation

49
Subsequent computations

50
So…

 byte buffer[] = SHA256(secret key)


 byte result[0-7] = (A * buffer[0-7]) + C
 byte result[8-15] = (A * result[0-7]) + C
 byte result[16-23] = (A * result[8-15]) + C

 … and same for the derived password

 From now on we will refer to:


 ‘result’ from secret key as X
 ‘result’ from derived password as Y
51
Inside encrypt (4)

52
Inside encrypt (5)

53
What’s happening

54
Tier 3 Solution

 Write a program to:


 Compute the password given a username*
 Base64 decode the string**
 Run the encryption algorithm in reverse to decrypt a
given input
 plaintext[i] = ciphertext[i] ^ (X[i] ^ Y[i])
 where you compute X and Y from the given secret key
and derived password

*Or just get it by running the Codebreaker binary in a


debugger
** Or do it online, use existing programs, etc.
55
Tier 3 Solution (2)

… on to Tier 4!

56
Tier 4 Solution
 You’d get the following message via email:

To:Tier3_Codebreakers
Msg:z/W4uhaRU+8N7/qKSzuwXfNPZ8Tf867ajNJ33tU85wTtgXywSTefsB86
3g26B5rR2Q9/oqFztnrT6nTUq8JMuJbWTUD5YIsN7uTbw6F9/GzsgdBG567
A303kSOTEM+Fsp7QialTheU9/W/02jiGZUeW6yYdhaMrDP6vDJlq+MNRMX
Zg8ereNKyBQDvGPR4iHUNBH0CP2oSb+/9WkeupRs2mkkoBAo8rdirZu0J
NOwnugF9T/Kw0R9EHVxNneIdDiG0m8O2UilAUaR6pKHTu1xS6MfkVh5C
KArmVTY6MAC6Vi8CnZJvM/WZT6cg6dLesgFrtXX8uwhzcTYwLe+t2m5Mv
vDtiZy0t9pLdBNAr6N3+znHCDInAIGlJe3shipbBQoqKxbb8VNY9DR4fJMG9
YIhnMyYn1g+mLGC41niWUqTbbBrnwSJgZ+u5AwLcpHXkA649O4IoHEyV+
bgWL/bKFVWL7KDAzEx4FdhwnYfe25SHirjFxVTrNiyR/FPPa/MgfixkrlVrZkY
GsZNlvDZjG8sxrH9tQ0kkOO7yaplHsBaYiwqCGVKum55iRyKgG1q2RuDAY
yzs1uvA2JnHnBZW1gEOpyy6RPiPuV7/z5DyQiMYhEzDA1Y9Dne92BagY0a
FTsCNMRX+W+L1XepcN49BEUDEMUKuUnLT6G+QuLw==

57
Tier 4 Solution (2)

 Maybe there’s a problem with the encryption


scheme…

58
Tier 4 Solution (3)

 plaintext[i] = ciphertext[i] ^ (X[i] ^ Y[i])

 byte buffer[] = SHA256(secret key)


 byte X[0-7] = (A * buffer[0-7]) + C
 byte X[8-15] = (A * X[0-7]) + C
 …

 byte buffer[] = SHA256(derived password)


 byte Y[0-7] = (A * buffer[0-7]) + C
 …

 We have the ciphertext, and the constants


59
Tier 4 Solution (4)
 plaintext[0-7] = ciphertext[0-7] ^ (X[0-7] ^ Y[0-7])

 byte buffer[] = SHA256(secret key)


 byte X[0-7] = (A * buffer[0-7]) + C
 byte X[8-15] = (A * X[0-7]) + C
 …

 byte buffer[] = SHA256(derived password)


 byte Y[0-7] = (A * buffer[0-7]) + C
 …

 All messages include the username too, from which we can


derive the password, and then the SHA256 hash
60
Tier 4 Solution (4)
 plaintext[0-7] = ciphertext[0-7] ^ (X[0-7] ^ Y[0-7])

 byte buffer[] = SHA256(secret key)


 byte X[0-7] = (A * buffer[0-7]) + C
 byte X[8-15] = (A * X[0-7]) + C
 …

 byte buffer[] = SHA256(derived password)


 byte Y[0-7] = (A * buffer[0-7]) + C
 …

 We know the plaintext at the beginning too, since the


program always adds ‘---MESSAGE BEGIN---’
61
Tier 4 Solution (5)
 plaintext[0-7] = ciphertext[0-7] ^ (X[0-7] ^ Y[0-7])

 byte buffer[] = SHA256(secret key)


 byte X[0-7] = (A * buffer[0-7]) + C
 byte X[8-15] = (A * X[0-7]) + C
 …

 byte buffer[] = SHA256(derived password)


 byte Y[0-7] = (A * buffer[0-7]) + C
 …

 Reversing the encryption equation, we get:

 X[0-7] = plaintext[0-7] ^ ciphertext[0-7] ^ Y[0-7]


62
Tier 4 Solution (6)
 plaintext[0-7] = ciphertext[0-7] ^ (X[0-7] ^ Y[0-7])

 byte buffer[] = SHA256(secret key)


 byte X[0-7] = (A * buffer[0-7]) + C
 byte X[8-15] = (A * X[0-7]) + C
 …

 byte buffer[] = SHA256(derived password)


 byte Y[0-7] = (A * buffer[0-7]) + C
 …

 X[8-15] and Y[8-15] (and on) are computed from the


SHA256 bytes, so we have the rest of those too. 
63
Tier 4 Solution (7)

 Decrypted message:

 Congratulations!! You have solved the final tier of


the Codebreaker Challenge! Please send us an
email at senior_project@[Link] and let us
know how you solved it. We hope you have
enjoyed working on this problem. If you are
interested in solving even more challenging and
exciting problems on a daily basis that directly
impact our national security posture and military
forces around the world, consider applying for a
career at NSA -- [Link]
64
Questions

?
… if this work interests you, consider applying for an internship or full-time
position at [Link]

Use event code 483-1 to associate yourself with the Codebreaker Challenge

65
Extra Slides

66
64-bit Data Types
Consider the following program:

int main(){
char one = 0x11; // sizeof(char) == 1
char two = 0x22;
int three = 0x33333333; // sizeof(int) == 4
int four = 0x44444444;
long long five = 0x5555555555555555; // sizeof(long long) == 8
long long six = 0x6666666666666666;
printf("8b: %hu 32b: %u 64b: %llu\n", one + two, three + four, five + six);
return 0;
}

67
64-bit Data Types – x86_64
Part 1: Move values onto the stack

mov BYTE PTR [rbp-0x2],0x11


mov BYTE PTR [rbp-0x1],0x22
mov DWORD PTR [rbp-0xc],0x33333333
mov DWORD PTR [rbp-0x8],0x44444444
mov DWORD PTR [rbp-0x20],0x55555555
mov DWORD PTR [rbp-0x1c],0x55555555
mov DWORD PTR [rbp-0x18],0x66666666
mov DWORD PTR [rbp-0x14],0x66666666

68
64-bit Data Types – x86_64
Part 2: Load into registers and compute

mov rax,QWORD PTR [rbp-0x18] // 0x6666666666666666 in rax


mov rdx,QWORD PTR [rbp-0x20] // 0x7777777777777777 in rdx
lea rcx,[rdx+rax*1] // rcx = rax + rdx*1
mov eax,DWORD PTR [rbp-0x8] // 0x44444444 in eax
mov edx,DWORD PTR [rbp-0xc] // 0x33333333 in edx
add edx,eax // edx = edx + eax
movsx esi,BYTE PTR [rbp-0x2] // 0x11 in esi
movsx eax,BYTE PTR [rbp-0x1] // 0x22 in eax
add esi,eax // esi = esi + eax

69
64-bit Data Types – x86
No 64-bit registers 

long long five = 0x5555555555555555; // sizeof(long long) == 8


long long six = 0x6666666666666666;

Let’s make it work with 32-bit ones!

70
64-bit Data Types – x86
Part 1: Move values onto the stack (same as x86_64)

mov BYTE PTR [ebp-1],0x11


mov BYTE PTR [ebp-2],0x22
mov DWORD PTR [ebp-8],0x33333333
mov DWORD PTR [ebp-12],0x44444444
mov DWORD PTR [ebp-24],0x55555555
mov DWORD PTR [ebp-20],0x55555555
mov DWORD PTR [ebp-32],0x66666666
mov DWORD PTR [ebp-28],0x66666666

71
64-bit Data Types – x86
Part 2: Load into registers and compute

mov eax,DWORD PTR [ebp-32] // 0x66666666 in eax


mov edx,DWORD PTR [ebp-28] // 0x66666666 in edx
add eax,DWORD PTR [ebp-24] // eax = eax + 0x55555555
adc edx,DWORD PTR [ebp-20] // edx = edx + 0x55555555 + CF

mov eax,DWORD PTR [ebp-12] // 0x444444 in eax
add eax,DWORD PTR [ebp-8] // eax = eax + 0x33333333

movsx edx,BYTE PTR [ebp-1] // 0x11 in edx
movsx eax,BYTE PTR [ebp-2] // 0x22 in eax
lea eax,[edx+eax] // eax = edx + eax*

72
Strings?

 The strings that are used here don’t appear in


the list of strings
 … or do they? Scroll down in the code to try
and spot them.

73
Explore Code Block (10)

74
Explore Code Block (11)

75
Inside special_printf

76
Inside special_printf (2)

77
Mystery solved!

78

You might also like