void test(){}
int main()
{
int a;
return 0
}
--- 위와 같은 소스코드가 있을때 !
변수 a의 주소로 가서 값을 변경하는건 쉬운데
&test의 함수 주소로 가서 값을 변경하니 에러가 납니다. 어떤식으로 바꿔줘야 에러없이 바꿔줄수 있을까요?
간단하게 API후킹하는 거라고 보시면 되지만 제가 하나씩 해보고 싶어서 연습중에 있습니다. 윈도우 보안때문에 에러가나는건 알곘는데 어떤식으로 우회? 혹은 커널단에서 직접? 어떤식으로 접근해야 할지 모르곘어요.
&test; 위치에 가서 233==0xE9 ==JMP 를 넣고 원하는 주소로 점프 즉 특정 함수 실행을 다른 함수로 실행하게 하고 싶어서 작업하고 있습니다.
당연히 메모리 에디터로 수정한다는 말이겠지? JMP 명령어 박으려면 E9만 박으면 안되고 그 뒤에 어디로 점프할 지도 적어줘야 되는데 문제는 절대 주소가 아니라 상대 주소야. JMP 명령어 다음 명령어로부터 몇 바이트 떨어졌는지의 값이 들어감. 가령 E9 00 00 00 00 이면 걍 바로 다음 명령어로 점프다.
ㅅㅅㅅ//아닙니다 프로그램에서 동작중에 인젝션 시켜서 수정하려고 합니다. 올리디버거로는 쉽게 수정이 가능했는데 c언어로 접근하니 에러가나서 고민중에 있습니다 (출발주소-목적주소-5) 였나 (목적주소-출발주소 -5)가 공식으로 알고 있습니다 :)
리틀엔디언방식으로 적어줘야 하는것도요 ㅋ;;
하시는 말씀은 이해 했습니다 다만.. 메모리에 값이 잘들어가나 테스트 중에 에러가나서 이렇게 메모리에 넣는게 아닌거 같아서 질문해봤습니다.
c언어할줄모르냐? 포인터쓰면되잖아
목적 주소 - (출발 주소 + JMP 명령어 길이(=5)) 가 공식이지.
포인터옵셌해서 값쓰면되겟구만
p=(char*)&test; *p=233 이렇게 넣었거든요;; 그리고 이후 주소는 +1 +2 +3 +4 해서 넣을 예정이였구요 ;;
x64(64비트)에서는 절대 주소로 점프가 가능하기 때문에 저런 계산을 할 필요가 없지만 말이야. 32비트(x86), 혹은 x64에서도 WOW64로 돌아가는 32비트 프로그램이라면 저런 계산은 필수적.
irene// 네 저도 포인터로 접근하면 될줄알았는데 로컬 변수 값은 접근하고 조작이 가능한데 함수 시작위치에 값은 조작이 안되더라구요 PE구조 .text에 값이 있어서 그런거같은데 어차피 메모리에 올라오면 상관없을꺼같아서 접근했더니 안되더라구요 그래서 질문해봤습니다 ㅠㅠ
*(char *)function = 0xE9; *(__int32 *)( (char *)function + 1 ) = (__int32)target - ((__int32)function + 5);
ㅅㅅㅅ// ㅠㅠ 맞아요 저 공식모르고 올리디버거로 분석하는데 멘붕터져서 이상한거 검색하며 하루를 날렸어요...
ㅅㅅㅅ/ 그렇게 접근하면 에러가나더라구요 (컴파일은 이상없고 ) 런타임에러
아 참. 기본적으로 실행 가능한 기계어 코드 데이터들은 전부 Read Only + Executable (PAGE_EXECUTE_READ) 메모리 페이지에 담기기 때문에 하기 전에 먼저 VirtualProtect(다른 프로세스라면 VirtualProtectEx) 함수로 Read + Write + Execute가 모두 가능한 PAGE_EXECUTE_READWRITE 권한으로 페이지 권한을 바꿔줄 필요가 있음.
당연히 (인젝션이 아닌 원격으로의) 다른 프로세스의 함수 후킹이라면 포인터가 아니라 WriteProcessMemory 함수를 써야 되는 것도 알고 있지?
아하 ㅠㅠ 제가 원하던답입니다 찾아봐야 곘네요 감사합니다 : )
아하 이해했어요 ㅋㅋ dll인젝션해서 작업할겁니다 :)
다들 감사합니다 .text 파일이라 안되는건 알고 있었는데 바꿔주는 함수가 있는줄몰랐어요 ㅠㅠ 감사합니다..!!
단어 필터링 때문에 덧글로는 안 써져서 --->
http://pastebin.com/TB12HhpL
ㅅㅅㅅ// 으억 검색까지 감사합니다 : )
검색이라니... 나를 뭘로 보고... 내가 방금 직접 짠 코드야.
ㄷㄷㄷ ㅠㅠ 감사합니다. 사실 포트폴리오로 백신 만들어보고 있는데 생각보다 많이 어렵네요 많은 도움이 되었습니다
병신인가 버츄얼 프로택트로 권한 바꾼뒤 해당 주소러 접근해서 데이터 바꾸고 다시 버츄얼 프로텍트러 권한 원래댜로 바꾸는게 기본중의 기본이거늘 치트엔진만 쓰다온 빠가새낀가 - DCW
이게 진짜 실행됨? 진짜 되면 보안성을 그냥 좆발라버릴 방법인데
백신이라... 재미난 거 하네. :) 바이러스 검사 및 치료를 위해 PE 포맷을 공부해야 할 거고, 실시간 감시 구현을 위해 API 후킹도 할 줄 알아야 하겠네. :p 백신이라는 게 뭐 대단한 기술이 있는 게 아니라 결국 악성코드 분석 노가다 + 시그너쳐 / 알고리즘 싸움이라서...
ㅇㅇ // 말이 심하네. 원래 다 저러면서 배우는 거야 ㅡㅡ; 치트 엔진이나 올리 디버거에서는 자동으로 해주기 때문에 눈치 채기가 어렵지.
상용 백신에서는 API 후킹 대신 커널 드라이버 짜서 파일 시스템 필터 드라이버를 만들지. 왜냐하면 64비트 OS에서는 패치 가드라는 게 있어서 커널단 후킹이 어렵거든.
ㅅㅅㅅ//맞아요 pe구조 외우느라 고생했어요 ㅋㅋ 웜바이러스 같은것도 만들고있거든요 많은 도움이 되었어요 :)
ㅇㅇ//헿 그래서 공부하고 있어요. 힘내라는 소리로 들을께요
뭐 결국 외우는 거지만 그렇게 어려운 구조도 아니야. 결국 가장 기본이 되는 핵심 정보는 파일 제일 앞의 MZ로 시작하는 도스 헤더, PE로 시작하는 PE 헤더(IMAGE_NT_HEADERS)랑 섹션 테이블이거든. 더 상세한 내용은 섹션들 안에 들어있고. 하지만 기본적으론 결국 실행 파일은 데이터를 메모리 배치에 따라 섹션으로 구분해서 나눠놓은 것에 불과함.
그리고 PE 이전에 NE, LE라는 것도 존재했다. PE가 Portable Executable의 약자인 것처럼 NE는 New Executable, LE는 Linear Executable의 약자인데 NE는 16비트 실행 파일, LE는 Windows 9x/Me 시절에 쓰였던 VxD 드라이버 포맷임.
그냥 참고적으로 저런 것도 있다는 것 정도는 상식으로 알아두면 좋아. 그리고 PE라는 게 유닉스의 실행 파일 포맷인 COFF에서 살짝 변형해서 파생된 거라 COFF에서 파생된 리눅스의 실행 파일 포맷인 ELF 포맷과도 상당히 유사함.
아 ..pe구조 배울때 처음 윈도우 이미지 헤더에 16비트 정보 값이나 그런게 있어서 PE구조부터인줄알았는데 아니였군요;;
윈도우 끝나면 리눅스도 한번 해봐야겠어요 다시한번 감사합니다 : )
윈도우 실행 파일 앞 부분에 MZ로 시작하는 헤더는 PE가 아니라 도스 실행 파일 부분이야. DOS stub이라고 불리지. e_lfanew 필드가 가리키는 PE로 시작되는 헤더부터가 진짜 PE 포맷이고 그 전까지는 DOS stub이라는 조그마한 도스 프로그램임. 그 프로그램이 하는 일은 도스에서 윈도우 실행 파일을 실행시키면 This program cannot be run in DOS mode.라는 문자열을 출력시키고 종료하는 간단한 프로그램임. 도스 입장에서 보면 PE 구조는 overlay 영역(파일의 유효 데이터 뒤에 붙은 잡다한 데이터)에 존재하는 더미 데이터일 뿐.
그렇게 공부해서 대부분 끝은 운영체제를 직접 만들어 보는 걸로 끝나더라. ㅋㅋ 나도 운영체제를 만들어 봤었고.
실행 파일 구조를 직접 설계해 보면 PE 포맷이 얼마나 좋은 포맷인지 절감하게 될 거다.
ㅋㅋㅋㅋ 으 해야 할게 많아서 신이 나네요 목적이 정해진거같아요 ㅋㅋ 운영체제 !
넵 그때 고생하고 있으면 ㅅㅅㅅ 님의 말을 생각할께요 ㅋㅋ
난 항상 이 갤러리에 있을 테니깐 언제든지 하다가 막히면 갤러리로 자주 놀러 와.
아 참고로 도스 헤더에서 MZ는 Mark Zbikowski라는 인간의 이니셜이야. ㅋ 이 사람이 도스 운영체제의 실행 파일 포맷을 설계한 MS 프로그래머거든.
넵 감사합니다.
ㅋㅋㅋ 아 그이야기는 들었어요 유명하더라구요 ㅋㅋ