์ƒ์„ธ ์ปจํ…์ธ 

๋ณธ๋ฌธ ์ œ๋ชฉ

[angr] fauxware

SYSTEM HACKING/CTF, etc

by koharin 2022. 5. 9. 23:52

๋ณธ๋ฌธ

728x90
๋ฐ˜์‘ํ˜•

๐Ÿ’ก์˜ˆ์ œ

angr-doc/examples/fauxware at master · angr/angr-doc

 

GitHub - angr/angr-doc: Documentation for the angr suite

Documentation for the angr suite. Contribute to angr/angr-doc development by creating an account on GitHub.

github.com

 

๐Ÿ’ก angr ํ™˜๊ฒฝ๊ตฌ์ถ•

dependancy

sudo apt-get install python3-dev libffi-dev build-essential virtualenvwrapper

 

install angr

mkvirtualenv --python=$(which python3) angr && pip install angr

virtualenvwrapper์—์„œ python ๊ฐ€์ƒ๋จธ์‹ ์„ ๋งŒ๋“ค๊ณ  ๊ฑฐ๊ธฐ์— angr๋ฅผ ์„ค์น˜ํ•ด์„œ ์‚ฌ์šฉํ•ด๋„ ๋˜๊ณ , ๊ทธ๋ƒฅ pip install angr๋กœ ์„ค์น˜ํ•ด์„œ ์‚ฌ์šฉํ•ด๋„ ๋œ๋‹ค.

deactivate # exit
workon angr # execute

 

angr ์‚ฌ์šฉ

import angr

angr๋Š” python์œผ๋กœ ๋งŒ๋“ค์–ด์กŒ๊ธฐ ๋•Œ๋ฌธ์— python์—์„œ angr๋ฅผ importํ•˜๋ฉด angr API ๋“ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

๐Ÿ’กCode Analysis

faux firmware์˜ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•ด๋ณด์ž.

main() ํ•จ์ˆ˜

int main(int argc, char **argv)
{
	char username[9];
	char password[9];
	int authed;

	username[8] = 0;
	password[8] = 0;

	printf("Username: \n");
	read(0, username, 8);
	read(0, &authed, 1);
	printf("Password: \n");
	read(0, password, 8);
	read(0, &authed, 1);

	authed = authenticate(username, password);
	if (authed) accepted();
	else rejected();
}
  • ์ง€์—ญ๋ณ€์ˆ˜ username, password์— ๊ฐ๊ฐ ์ด๋ฆ„๊ณผ ํŒจ์Šค์›Œ๋“œ๋ฅผ ์ž…๋ ฅ๋ฐ›๊ณ  authed๋ฅผ ์ž…๋ ฅ๋ฐ›๋Š”๋‹ค.
  • authenticate ํ•จ์ˆ˜ ํ˜ธ์ถœ๋กœ ํŠน์ • ์ž‘์—… ์ˆ˜ํ–‰ ํ›„ ๊ฒฐ๊ณผ๋ฅผ authed์— ์ €์žฅํ•˜๊ณ , authed๊ฐ€ 0์ด ์•„๋‹ˆ๋ฉด accepted() ํ•จ์ˆ˜๋ฅผ, 0์ด๋ฉด rejected() ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.

 

accepted() ํ•จ์ˆ˜, rejected() ํ•จ์ˆ˜

int accepted()
{
	printf("Welcome to the admin console, trusted user!\n");
}

int rejected()
{
	printf("Go away!");
	exit(1);
}

๋‘ ํ•จ์ˆ˜๋Š” ๋‹จ์ˆœํžˆ ๋ฌธ์ž์—ด์„ ์ถœ๋ ฅํ•ด์ฃผ๋Š”๋ฐ, ๋‘ ํ•จ์ˆ˜ ํ˜ธ์ถœ ํ›„ ์ข…๋ฃŒ๋œ๋‹ค.

 

authenticated() ํ•จ์ˆ˜

char *sneaky = "SOSNEAKY";

int authenticate(char *username, char *password)
{
	char stored_pw[9];
	stored_pw[8] = 0;
	int pwfile;

	// evil back d00r
	if (strcmp(password, sneaky) == 0) return 1;

	pwfile = open(username, O_RDONLY);
	read(pwfile, stored_pw, 8);

	if (strcmp(password, stored_pw) == 0) return 1;
	return 0;

}
  • password์™€ sneaky๋ฅผ ๋น„๊ตํ•ด์„œ ์ผ์น˜ํ•˜๋ฉด 1์„ ๋ฆฌํ„ดํ•œ๋‹ค.
  • password๊ฐ€ sneaky์™€ ๋‹ค๋ฅธ ๊ฒฝ์šฐ username ํŒŒ์ผ์„ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ์—ด์–ด์„œ pwfile๋ฅผ ํŒŒ์ผ ํฌ์ธํ„ฐ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.
  • ํŒŒ์ผ์—์„œ stored_pw์— 8๋ฐ”์ดํŠธ๋งŒํผ ์ฝ๊ณ  password๊ฐ€ stored_pw์™€ ๋™์ผํ•˜๋ฉด ์ •์ƒ์œผ๋กœ 1์„ ๋ฆฌํ„ดํ•˜๊ณ  ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด 0์„ ๋ฆฌํ„ดํ•œ๋‹ค.

 

 

๐Ÿ’กExploit using angr

sneaky ๊ฐ’์ด "SOSNEAKY"์ธ๊ฑธ ์•Œ๊ธฐ ๋•Œ๋ฌธ์— ์ž„์˜์˜ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฐฑ๋„์–ด์ธ sneaky๋ฅผ ํ†ตํ•ด password๊ฐ€ ์ธ์ฆ๋˜๋„๋ก ๋งŒ๋“ ๋‹ค.

angr์— ๋ฐ”์ด๋„ˆ๋ฆฌ ๋กœ๋“œํ•˜๊ธฐ

project = angr.Project('fauxware', auto_load_libs=False)

‘fauxware’ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ถ„์„ ์œ„ํ•ด angr.Project() API ์‚ฌ์šฉํ•˜์—ฌ angr Project๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

 

state ์ƒ์„ฑ

state = project.factory.entry_state()

๋ฐ”์ด๋„ˆ๋ฆฌ entrypoint์—์„œ ํ”„๋กœ๊ทธ๋žจ ์ƒํƒœ๋ฅผ SimState ๊ฐ์ฒด๋กœ ๋ฆฌํ„ดํ•œ๋‹ค.

 

Simulation Managers ์‚ฌ์šฉ1

simulation manager๋Š” ์ƒํƒœ๋“ค์„ stash๋กœ ๊ตฌ์„ฑํ•˜๊ณ  filter, merge, move์˜ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋””ํดํŠธ stash๋Š” active stash๋กœ, ์ƒˆ๋กœ์šด simulation manager๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋ฉด ์ƒํƒœ๊ฐ€ active stash๋กœ ๋“ค์–ด๊ฐ„๋‹ค.

simulation manager๋Š” ํ•œ basic block์—์„œ ๋ชจ๋“  ์ƒํƒœ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ฉด stash์— ๋„ฃ๋Š”๋‹ค.

>>> simgr = proj.factory.simgr(state)
>>> simgr.run()
<SimulationManager with 3 deadended>

symbolic branch ์กฐ๊ฑด์ธ ์ƒํƒœ๊ฐ€ ๋ฐœ๊ฒฌ๋˜๋ฉด, ๋‘ ๋ถ„๊ธฐ์— ๋Œ€ํ•œ successor ์ƒํƒœ๊ฐ€ stash์— ๋“ค์–ด๊ฐ€๊ณ  ๋‘ ์ƒํƒœ์— ๋Œ€ํ•ด ์‹คํ–‰์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. run() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋” ์ด์ƒ ์ฒ˜๋ฆฌํ•  ๊ฒƒ์ด ์—†์„ ๋•Œ๊นŒ์ง€ ์ง„ํ–‰ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

>>> simgr.move(from_stash='deadended', to_stash='authenticated', filter_func=lambda s:b'Welcome' in s.posix.dumps(1))
<SimulationManager with 1 deadended, 2 authenticated>

deadended state๋Š” exit ์‹œ์Šคํ…œ์ฝœ ๋“ฑ์œผ๋กœ ์ธํ•ด ์ƒํƒœ๊ฐ€ successor๋ฅผ ๋งŒ๋“œ๋Š”๋ฐ ์‹คํŒจํ•œ ๊ฒƒ์œผ๋กœ active stash์—์„œ ์ œ๊ฑฐ๋˜๊ณ  deadended stash์— ๋“ค์–ด๊ฐ„๋‹ค. ๋”ฐ๋ผ์„œ ์ฃผ์–ด์ง„ ๋ฐ”์ด๋„ˆ๋ฆฌ์—์„œ ์ •์ƒ ์ข…๋ฃŒ๋“  ๋น„์ •์ƒ ์ข…๋ฃŒ๋“  exit() ์‹œ์Šคํ…œ์ฝœ์ด ํ˜ธ์ถœ๋˜๋ฉด์„œ ์ข…๋ฃŒ๋˜๋ฏ€๋กœ ๋‘ ์ƒํƒœ ๋ชจ๋‘ deadended stash์— ์žˆ์„ ๊ฒƒ์ด๋‹ค.

deadended stash์—์„œ ์ƒํƒœ๊ฐ€ ๊ฐ€์ง€๋Š” ๋ฌธ์ž์—ด๋“ค์„ ์‚ดํŽด๋ณด๋ฉด, dumps(1)์— authenticated ์กฐ๊ฑด์ผ ๋•Œ ์ถœ๋ ฅ๋˜๋Š” ๋ฌธ์ž์—ด ๋˜๋Š” authenticated๊ฐ€ ์•„๋‹ ๋•Œ ์ถœ๋ ฅ๋˜๋Š” ๋ฌธ์ž์—ด์ด ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ deadended stash ๋‚ด ์ƒํƒœ ์ค‘์—์„œ dumps(1)๋กœ ๊ตฌํ•œ ๋ฌธ์ž์—ด์ด ‘Welcome’์„ ํฌํ•จํ•˜๋ฉด authenticated stash๋กœ ์˜ฎ๊ธด๋‹ค.

move() ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ถœ๋ ฅ์— ์ฃผ์–ด์ง„ ๋ฌธ์ž์—ด์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉด from_stash์—์„œ to_stash๋กœ ์ƒํƒœ๋ฅผ ์˜ฎ๊ธธ ์ˆ˜ ์žˆ๋‹ค.

3๊ฐœ์˜ deadended stash์— ์žˆ๋Š” ์ƒํƒœ ์ค‘ ‘Welcome’ ๋ฌธ์ž์—ด์„ ์ถœ๋ ฅ์— ํฌํ•จํ•˜๋Š” ์ƒํƒœ 2๊ฐœ๊ฐ€ authenticated stash๋กœ ์ด๋™์‹œํ‚จ๋‹ค.

 

>>> for s in simgr.deadended + simgr.authenticated:
...     print(hex(s.addr))
... 
0x746a70
0xa00058
0xa00058
>>> simgr.one_deadended
<SimState @ 0x746a70>
>>> simgr.mp_authenticated
MP([<SimState @ 0xa00058>, <SimState @ 0xa00058>])

one_์„ stash ์ด๋ฆ„ ์•ž์— ์‚ฌ์šฉํ•˜๋ฉด stash ๋‚ด ์ฒซ ๋ฒˆ์งธ state๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

mp_์„ stash ์ด๋ฆ„ ์•ž์— ์‚ฌ์šฉํ•˜๋ฉด stash ๋‚ด ๋ชจ๋“  ์ƒํƒœ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

 

>>> simgr.mp_authenticated.posix.dumps(0)
MP([b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00SOSNEAKY\\x00', b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x04\\x10\\x10\\x80\\x80\\x80\\x00\\x00'])

stash ๋‚ด ์ƒํƒœ์— ๋Œ€ํ•œ ๋‚ด์šฉ์„ ๊ตฌํ•œ๋‹ค.

 

#!/usr/bin/python
import angr
 
# load binary into angr project
project = angr.Project('fauxware', auto_load_libs=False)

# program state in entrypoint
state = project.factory.entry_state()

# Create Simulation Manager
simgr = project.factory.simgr(state)

# step until nothing left to step
simgr.run()
print(simgr)
print(simgr.deadended)

for i in range(len(simgr.deadended)):
    str = simgr.deadended[i].posix.dumps(1)
    if b'Welcome' in str:
        print(simgr.deadended[i], end=' ')
        print(str)

 

Simulation Manager ์‚ฌ์šฉ2

>>> import angr
>>> p = angr.Project('fauxware')
>>> state=p.factory.entry_state()
>>> simgr=p.factory.simgr(state)
>>> simgr.run(until=lambda sm:len(sm.active) > 1)
<SimulationManager with 2 active>
>>> simgr.active[0].posix.dumps(1)
b'Username: \\nPassword: \\n'
>>> simgr.active[0].posix.dumps(2)
b''
>>> simgr.active[0].posix.dumps(0)
b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00SOSNEAKY\\x00'
>>> simgr.active[1].posix.dumps(0)
b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00@@\\x10@\\x01@\\x02\\x00\\x00'
>>> simgr.active[1].posix.dumps(1)
b'Username: \\nPassword: \\n'
>>> for i in range(len(simgr.active)):
...     if b'SOSNEAKY' in simgr.active[i].posix.dumps(0):
...             r = simgr.active[i].posix.dumps(0)
... 
>>> print(r)
b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00SOSNEAKY\\x00'
>>> assert b'SOSNEAKY' in simgr.active[1].posix.dumps(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError
>>> import sys
>>> sys.stdout.buffer.write(simgr.active[0].posix.dumps(0))
SOSNEAKY18

 

728x90
๋ฐ˜์‘ํ˜•

๊ด€๋ จ๊ธ€ ๋”๋ณด๊ธฐ