ELF-No software breakpoints

ELF-No software breakpoints

ELF-No software breakpoints 题目链接

0x01 IDA分析

下载二进制文件,IDA打开后发现,在start函数中:

1
2
3
4
5
6
7
8
9
10
.text:08048096                 mov     eax, 3
.text:0804809B xor ebx, ebx ; fd
.text:0804809D mov ecx, offset byte_8049188 ; addr
.text:080480A2 mov edx, 33h ; len
.text:080480A7 int 80h ; LINUX - sys_read
.text:080480A9 xor ecx, ecx
.text:080480AB mov eax, offset start
.text:080480B0 mov ebx, 8048123h
.text:080480B5 call sub_8048115
.text:080480BA mov edx, ecx

其中,password读入byte_8049188内存区域中,之后调用sub_8048115函数进行一系列处理。
sub_8048115(&start, 0x8048123)为传入参数内容。start为函数的代码段首地址,0x8048123位代码段末地址,函数的返回值放入ecx中。

sub_8048115函数:

1
2
3
4
5
6
7
8
9
10
11
12
.text:08048115 sub_8048115     proc near               ; CODE XREF: start+35↑p
.text:08048115 sub ebx, eax
.text:08048117 xor ecx, ecx
.text:08048119
.text:08048119 loc_8048119: ; CODE XREF: sub_8048115+B↓j
.text:08048119 add cl, [eax]
.text:0804811B rol ecx, 3
.text:0804811E inc eax
.text:0804811F dec ebx
.text:08048120 jnz short loc_8048119
.text:08048122 retn
.text:08048122 sub_8048115 endp

函数进入后首先计算长度sub ebx, eax,即len = 0x8048123 - &start
之后循环计算出key放入exc中。循环次数为ebx。计算过程为:

1
2
3
4
for i in range(len):
add cl, [eax]
rol ecx, 3
inc eax

之后继续分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.text:080480BA                 mov     edx, ecx
.text:080480BC mov ecx, 19h
.text:080480C1
.text:080480C1 loc_80480C1: ; CODE XREF: start+5C↓j
.text:080480C1 mov eax, offset byte_8049155
.text:080480C6 mov ebx, offset byte_8049188
.text:080480CB ror edx, 1
.text:080480CD mov al, [eax+ecx-1]
.text:080480D1 mov bl, [ebx+ecx-1]
.text:080480D5 xor al, bl
.text:080480D7 xor al, dl
.text:080480D9 jnz short loc_80480F6
.text:080480DB dec ecx
.text:080480DC jnz short loc_80480C1

可以看出,将sub_8048115函数的结果取出放入edx中,ecx赋值为25(0x19h)。
之后即为循环比较password,计算公式:

1
2
3
password \oplus str = key

password = str \oplus key
1
2
3
4
5
for i in len:
temp = str[i] ^ password[i]
ror key, 1
if temp != (uint8_t)key:
break

计算password即可

0x02 源代码

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
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <inttypes.h>
#include <fcntl.h>
#include <string.h>

#define _cror_(a, N, n) (a << (N - n) | a >> n)
#define _crol_(a, N, n) (a >> (N - n) | a << n)


uint32_t temp = 0xac77e166;

void cal()
{
unsigned char buf[164] =
"\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xb9\xa1\x91\x04"
"\x08\xba\x26\x00\x00\x00\xcd\x80\xb8\x03\x00\x00\x00\x31"
"\xdb\xb9\x88\x91\x04\x08\xba\x33\x00\x00\x00\xcd\x80\x31"
"\xc9\xb8\x80\x80\x04\x08\xbb\x23\x81\x04\x08\xe8\x5b\x00"
"\x00\x00\x89\xca\xb9\x19\x00\x00\x00\xb8\x55\x91\x04\x08"
"\xbb\x88\x91\x04\x08\xd1\xca\x8a\x44\x08\xff\x8a\x5c\x0b"
"\xff\x30\xd8\x30\xd0\x75\x1b\x49\x75\xe3\xb8\x04\x00\x00"
"\x00\xbb\x01\x00\x00\x00\xb9\x24\x91\x04\x08\xba\x26\x00"
"\x00\x00\xcd\x80\xeb\x16\xb8\x04\x00\x00\x00\xbb\x01\x00"
"\x00\x00\xb9\x4a\x91\x04\x08\xba\x0b\x00\x00\x00\xcd\x80"
"\xb8\x01\x00\x00\x00\x31\xdb\xcd\x80\x29\xc3\x31\xc9\x02"
"\x08\xc1\xc1\x03\x40\x4b\x75\xf7\xc3";
temp = 0;
for (auto i = 0; i < 163; i++)
{
temp = (temp & 0xFFFFFF00) + (uint8_t)(buf[i] + temp & 0xFF);
temp = _crol_(temp, 32, 3);
}
}

int main()
{
uint8_t buf[25] = {0x1E, 0xCD, 0x2A, 0xD5, 0x34, 0x87, 0xFC, 0x78, 0x64, 0x35, 0x9D, 0xEC, 0xDE, 0x15, 0xAC, 0x97, 0x99, 0xAF, 0x96, 0xDA, 0x79, 0x26, 0x4F, 0x32, 0xE0};
uint8_t password[26];
password[25] = 0x0;
cal();
printf("key:%X\n", temp);
printf("buf, pass, key\n");
for (int i = 24; i >= 0; i--)
{
temp = _cror_(temp, 32, 1);
password[i] = buf[i] ^ (uint8_t)temp;
printf("%3X, %4c, %3X\n", buf[i], (uint8_t)password[i], (uint8_t)temp);
}
printf("password: %s\n", password);
return 0;
}