代码是动态解密的,简单的xor,解密一块执行一块。每一块结尾会设置rbx,rbx决定下一块被解密的代码。
实际上每一块代码相当于一个节点,里面有一个根据输入的jz,决定下一个rbx以及一个cost,所以相当于一颗二叉树。
每次经过一个节点都会累加cost。
根节点对应的代码块会判断cost是否小于等于某个值,然后输出成功信息。
如果只有唯一解那么显然是找最短路。
解题思路是beaengine解析代码生成图,用dijkstra算法求最短路并输出路径。
事实上只有一条最短路,刚刚等于那个值。
自己打oi时留下的板子,忘记有没有加优化了,不过这个版本比较方便记录path
using namespace std;
typedef struct Block {
int
index;
char buf[
32
];
};
int
path[
25503
][
4
]
=
{
0
, };
/
/
0
(path
/
rbx,cost)
1
(path
/
rbx,cost)
queue<pair<
int
, Block
*
>> rbxs;
/
/
rbx(xor offset), lastBlock
int
sa
=
0x176
;
BYTE
*
firstBlock;
int
blockNum
=
0
;
set
<
int
> dised;
Block xorBlock
=
{
0
,
0x48
,
0xc7
,
0xc0
,
0x01
,
0x00
,
0x00
,
0x00
,
0x48
,
0xc7
,
0xc7
,
0x01
,
0x00
,
0x00
,
0x00
,
0x48
,
0xc7
,
0xc2
,
0x05
,
0x00
,
0x00
,
0x00
,
0x49
,
0x81
,
0xf9
,
0xda
,
0x49
,
0x00
,
0x00
,
0x7f
,
0x07
,
0x4c
,
0x89
};
Block
*
Xor(char
*
firstBlock, UInt64 offset, Block &oldBlock)
{
Block
*
pB
=
new Block();
pB
-
>index
=
offset >>
5
;
blockNum
+
+
;
char
*
xorBuf
=
firstBlock
+
offset;
for
(
int
i
=
0
; i <
32
; i
+
+
) {
pB
-
>buf[i]
=
xorBuf[i] ^ oldBlock.buf[i];
}
return
pB;
}
void Jmp(DISASM& infos)
{
UINT64 nextVA
=
infos.Instruction.AddrValue;
UINT64 curVA
=
infos.VirtualAddr;
/
/
jmp
infos.EIP
+
=
nextVA
-
curVA;
infos.VirtualAddr
=
nextVA;
}
void DisasmCode(char
*
stBuf, UINT64 stVA, Block
*
curBlock,
int
rbx,
int
branch)
{
DISASM infos;
size_t
len
;
/
/
init
memset(&infos,
0
, sizeof(DISASM));
infos.EIP
=
(UINT64)stBuf;
infos.VirtualAddr
=
(UINT64)stVA;
while
(infos.Error
=
=
0
) {
/
/
limit
UInt64 offset
=
infos.EIP
-
(UINT64)curBlock
-
>buf;
if
(offset <
0
|| offset >
=
32
) {
break
;
}
if
(infos.VirtualAddr
=
=
0x400080
) {
/
/
xor
rbxs.push(make_pair(rbx, curBlock));
break
;
}
/
/
disasm
len
=
Disasm(&infos);
cout <<
hex
<< infos.VirtualAddr <<
" "
<< infos.CompleteInstr << endl;
/
/
jmp
if
(infos.Instruction.BranchType
=
=
JmpType) {
if
(infos.Instruction.AddrValue
=
=
0x400080
) {
/
/
xor
rbxs.push(make_pair(rbx, curBlock));
break
;
}
Jmp(infos);
}
/
/
jmp
if
(infos.Instruction.BranchType) {
/
/
false branch
DisasmCode((char
*
)(infos.EIP
+
len
), infos.VirtualAddr
+
len
, curBlock, rbx,
0
);
/
/
true branch
branch
=
1
;
Jmp(infos);
continue
;
}
/
/
if
modified rbx (
0x8
)
if
(((infos.Operand1.AccessMode
=
=
WRITE) && (infos.Operand1.Registers.gpr & REG3))) {
rbx
+
=
infos.Operand2.Memory.Displacement;
}
/
/
if
add r9 (
0x200
)
if
((infos.Operand1.AccessMode
=
=
3
) && (infos.Operand1.Registers.gpr &
0x200
)) {
if
(branch >
=
0
) {
path[curBlock
-
>index][branch
*
2
]
=
rbx >>
5
;
path[curBlock
-
>index][branch
*
2
+
1
]
=
infos.Instruction.Immediat;
}
}
/
/
go on
infos.EIP
+
=
len
;
infos.VirtualAddr
+
=
len
;
}
}
int
main()
{
ifstream fin;
ofstream fout;
BYTE
*
fileBuf;
Block
*
lastBlock;
Block
*
pB;
/
/
read
file
fin.
open
(
"E:\\works\\ctf\\21pbctf\\re_BinaryTree\\main.elf"
, ios::
in
| ios::binary);
fin.seekg(
0
, ios::end);
size_t fileSize
=
fin.tellg();
fin.seekg(
0
, ios::beg);
fileBuf
=
(BYTE
*
)malloc(fileSize);
fin.read((char
*
)fileBuf, fileSize);
cout <<
"fileSize:"
<< dec << fileSize << endl;
fin.close();
/
/
disasm
firstBlock
=
fileBuf
+
sa;
cout <<
"rbx:0"
<< endl;
pB
=
Xor((char
*
)firstBlock,
0
, xorBlock);
dised.insert(
0
);
DisasmCode(pB
-
>buf,
0x4000AD
, pB,
0
,
0
);
while
(!rbxs.empty()) {
pair<
int
, Block
*
> t
=
rbxs.front();
rbxs.pop();
lastBlock
=
t.second;
cout <<
"num:"
<< dec << blockNum << endl;
/
/
0x639f
*
2
if
(dised.insert(t.first).second) {
/
/
not
disasm
pB
=
Xor((char
*
)firstBlock, t.first,
*
lastBlock);
/
/
disasm
DisasmCode(pB
-
>buf,
0x4000AD
, pB,
0
,
-
1
);
}
}
/
/
write
file
fout.
open
(
"E:\\works\\ctf\\21pbctf\\re_BinaryTree\\main_.elf"
, ios::out | ios::binary);
fout.write((char
*
)fileBuf, fileSize);
fout.close();
/
/
write
file
fout.
open
(
"E:\\works\\ctf\\21pbctf\\re_BinaryTree\\path.txt"
, ios::out);
for
(
int
i
=
0
; i < blockNum; i
+
+
) {
fout << path[i][
0
] <<
" "
<< path[i][
1
] <<
" "
<< path[i][
2
] <<
" "
<< path[i][
3
] << endl;
}
fout.close();
fout.
open
(
"E:\\works\\ctf\\21pbctf\\re_BinaryTree\\pathDij.txt"
, ios::out);
int
E
=
0
;
for
(
int
i
=
0
; i < blockNum; i
+
+
) {
if
(path[i][
1
]) {
fout << i <<
" "
<< path[i][
0
] <<
" "
<< path[i][
1
] << endl;
fout << i <<
" "
<< path[i][
2
] <<
" "
<< path[i][
3
] << endl;
E
+
=
2
;
}
else
{
cout << i <<
","
;
}
}
cout << endl;
fout.close();
cout <<
"N E\n"
;
cout << dec << blockNum <<
" "
<< E << endl;
/
/
25503
50942
0
return
0
;
}
using namespace std;
typedef struct Block {
int
index;
char buf[
32
];
};
int
path[
25503
][
4
]
=
{
0
, };
/
/
0
(path
/
rbx,cost)
1
(path
/
rbx,cost)
queue<pair<
int
, Block
*
>> rbxs;
/
/
rbx(xor offset), lastBlock
int
sa
=
0x176
;
BYTE
*
firstBlock;
int
blockNum
=
0
;
set
<
int
> dised;
Block xorBlock
=
{
0
,
0x48
,
0xc7
,
0xc0
,
0x01
,
0x00
,
0x00
,
0x00
,
0x48
,
0xc7
,
0xc7
,
0x01
,
0x00
,
0x00
,
0x00
,
0x48
,
0xc7
,
0xc2
,
0x05
,
0x00
,
0x00
,
0x00
,
0x49
,
0x81
,
0xf9
,
0xda
,
0x49
,
0x00
,
0x00
,
0x7f
,
0x07
,
0x4c
,
0x89
};
Block
*
Xor(char
*
firstBlock, UInt64 offset, Block &oldBlock)
{
Block
*
pB
=
new Block();
pB
-
>index
=
offset >>
5
;
blockNum
+
+
;
char
*
xorBuf
=
firstBlock
+
offset;
for
(
int
i
=
0
; i <
32
; i
+
+
) {
pB
-
>buf[i]
=
xorBuf[i] ^ oldBlock.buf[i];
}
return
pB;
}
void Jmp(DISASM& infos)
{
UINT64 nextVA
=
infos.Instruction.AddrValue;
UINT64 curVA
=
infos.VirtualAddr;
/
/
jmp
infos.EIP
+
=
nextVA
-
curVA;
infos.VirtualAddr
=
nextVA;
}
void DisasmCode(char
*
stBuf, UINT64 stVA, Block
*
curBlock,
int
rbx,
int
branch)
{
DISASM infos;
size_t
len
;
/
/
init
memset(&infos,
0
, sizeof(DISASM));
infos.EIP
=
(UINT64)stBuf;
infos.VirtualAddr
=
(UINT64)stVA;
while
(infos.Error
=
=
0
) {
/
/
limit
UInt64 offset
=
infos.EIP
-
(UINT64)curBlock
-
>buf;
if
(offset <
0
|| offset >
=
32
) {
break
;
}
if
(infos.VirtualAddr
=
=
0x400080
) {
/
/
xor
rbxs.push(make_pair(rbx, curBlock));
break
;
}
/
/
disasm
len
=
Disasm(&infos);
cout <<
hex
<< infos.VirtualAddr <<
" "
<< infos.CompleteInstr << endl;
/
/
jmp
if
(infos.Instruction.BranchType
=
=
JmpType) {
if
(infos.Instruction.AddrValue
=
=
0x400080
) {
/
/
xor
rbxs.push(make_pair(rbx, curBlock));
break
;
}
Jmp(infos);
}
/
/
jmp
if
(infos.Instruction.BranchType) {
/
/
false branch
DisasmCode((char
*
)(infos.EIP
+
len
), infos.VirtualAddr
+
len
, curBlock, rbx,
0
);
/
/
true branch
branch
=
1
;
Jmp(infos);
continue
;
}
/
/
if
modified rbx (
0x8
)
if
(((infos.Operand1.AccessMode
=
=
WRITE) && (infos.Operand1.Registers.gpr & REG3))) {
rbx
+
=
infos.Operand2.Memory.Displacement;
}
/
/
if
add r9 (
0x200
)
if
((infos.Operand1.AccessMode
=
=
3
) && (infos.Operand1.Registers.gpr &
0x200
)) {
if
(branch >
=
0
) {
path[curBlock
-
>index][branch
*
2
]
=
rbx >>
5
;
path[curBlock
-
>index][branch
*
2
+
1
]
=
infos.Instruction.Immediat;
}
}
/
/
go on
infos.EIP
+
=
len
;
infos.VirtualAddr
+
=
len
;
}
}
int
main()
{
ifstream fin;
ofstream fout;
BYTE
*
fileBuf;
Block
*
lastBlock;
Block
*
pB;
/
/
read
file
fin.
open
(
"E:\\works\\ctf\\21pbctf\\re_BinaryTree\\main.elf"
, ios::
in
| ios::binary);
fin.seekg(
0
, ios::end);
size_t fileSize
=
fin.tellg();
fin.seekg(
0
, ios::beg);
fileBuf
=
(BYTE
*
)malloc(fileSize);
fin.read((char
*
)fileBuf, fileSize);
cout <<
"fileSize:"
<< dec << fileSize << endl;
fin.close();
/
/
disasm
firstBlock
=
fileBuf
+
sa;
cout <<
"rbx:0"
<< endl;
pB
=
Xor((char
*
)firstBlock,
0
, xorBlock);
dised.insert(
0
);
DisasmCode(pB
-
>buf,
0x4000AD
, pB,
0
,
0
);
while
(!rbxs.empty()) {
pair<
int
, Block
*
> t
=
rbxs.front();
rbxs.pop();
lastBlock
=
t.second;
cout <<
"num:"
<< dec << blockNum << endl;
/
/
0x639f
*
2
if
(dised.insert(t.first).second) {
/
/
not
disasm
pB
=
Xor((char
*
)firstBlock, t.first,
*
lastBlock);
/
/
disasm
DisasmCode(pB
-
>buf,
0x4000AD
, pB,
0
,
-
1
);
}
}
/
/
write
file
fout.
open
(
"E:\\works\\ctf\\21pbctf\\re_BinaryTree\\main_.elf"
, ios::out | ios::binary);
fout.write((char
*
)fileBuf, fileSize);
fout.close();
/
/
write
file
fout.
open
(
"E:\\works\\ctf\\21pbctf\\re_BinaryTree\\path.txt"
, ios::out);
for
(
int
i
=
0
; i < blockNum; i
+
+
) {
fout << path[i][
0
] <<
" "
<< path[i][
1
] <<
" "
<< path[i][
2
] <<
" "
<< path[i][
3
] << endl;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-10-15 21:52
被wx_御史神风编辑
,原因: