메뉴 닫기

Samsung 850 Pro 펌웨어 분석 (1)

ssd 교체 각을 재고있는데, 만약 교체한다면 1TB SSD를 살꺼고, 그러면 현재 256gb(850 pro) + 512gb(mx500) 구성이 512gb(mx500) + 1tb(???)가 될 가능성이 크다.

그렇게 된다면 850 pro 256gb하나가 잉여가 되는데, 이걸 어떻게 굴려먹을까 생각을 하는중이다.

내가 해보고 싶은건 3가지 정도인데,, 첫째는 이 MLC SSD를 TLC로 바꾸는것.(먼 개소리냐고 하실지 모르겠지만 mlc tlc 같은건 어차피 컨트롤러가 결정하는 부분이라 가능하다.) 둘째는 SSD 펌웨어 업데이트에서 실질적으로 무엇이 변했는지 파악해보는거고, 세번째는 서로다른 ssd 펌웨어의 차이를 알아보는것이다.

아마 두번째, 세번째는 별로 안어려울것 같은데 첫번째는 글쎄?! 할 수 있으려나 뭐 암튼.

 

https://www.samsung.com/semiconductor/minisite/ssd/product/consumer/850pro/

일단은 여기서 '850 PRO Firmware for Window User'를 다운로드 받자.

Mac User용도 있는데 아마 둘 차이는 부팅파일의 구성이다. 맥 유저용은 efi환경에서 부팅가능하게끔 이미지를 구성해뒀다.

iso파일을 보면, isolinux가 있는데, 뇌피셜좀 돌려보면, 콩알만한 리눅스로 부팅해서 ssd에 펌웨어를 쓰는 그런 형태인 것 같다.

그래서 initrd를 보면 gzip compress data이고 압축을 풀면 cpio archive가 나온다.

/root에 보면 예상했던대로 fumagician라는 프로그램과 펌웨어 파일이 있다. 물런 암호화된 펌웨어 파일이지만,,

 

여기서 잔대가리를 굴려서 github를 슥슥 뒤지니까 "https://github.com/ddcc/drive_firmware" 이런게 나왔다.

근데 돌려보니까 얘네들이 암호화 로직을 바꿨는지, S470같은 구대기 SSD 펌웨어에서는 잘 되는데, 내가 잡고있는 850 pro에서는 안된다,,ㅜㅜㅜ

 

그래서 fumagician 프로그램을 분석해보았다.

fumagician프로그램을 분석해보면 구성이 상당히 간단한데, AES-128(CTR Mode) 로 DSRD.enc를 복호화하고, 거기 적힌 뭔가를 보고 EXM04B6Q.enc를 복호화해서 zip으로 압축을 푼다.

그 뒤는 뭐 또 뇌피셜좀 돌리면 실제 ssd에 펌웨어를 쓰는 과정일 것 같다. (사실 그 뒤까지는 안봄 ㅎㅎ;)

 

#include<stdio.h>
#include<stdlib.h>

/* https://github.com/kokke/tiny-AES-c */

#include "aes.h"
#include "aes.c"


/*
Ref -> RFC 3602
*/
unsigned char AES_KEY[16] = {
	0x56, 0xE4, 0x7A, 0x38, 0xC5, 0x59, 0x89, 0x74, 0xBC, 0x46, 0x90, 0x3D,
	0xBA, 0x29, 0x03, 0x49
};

unsigned char CTR_IV[16] = {
	0x8C, 0xE8, 0x2E, 0xEF, 0xBE, 0xA0, 0xDA, 0x3C, 0x44, 0x69, 0x9E, 0xD7,
	0xDB, 0x51, 0xB7, 0xD9
};


unsigned char SubTable[256] = {
	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
	0x1C, 0x1D, 0x1E, 0x1F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
	0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x50, 0x51, 0x52, 0x53,
	0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B,
	0x7C, 0x7D, 0x7E, 0x7F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
	0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xB0, 0xB1, 0xB2, 0xB3,
	0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
	0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB,
	0xDC, 0xDD, 0xDE, 0xDF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
	0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xE0, 0xE1, 0xE2, 0xE3,
	0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
	0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB,
	0xCC, 0xCD, 0xCE, 0xCF, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
	0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0x80, 0x81, 0x82, 0x83,
	0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
	0x6C, 0x6D, 0x6E, 0x6F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
	0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x20, 0x21, 0x22, 0x23,
	0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
	0x0C, 0x0D, 0x0E, 0x0F
};

unsigned char InvSubTable[256];

void __cdecl incr_iv(unsigned __int8 *a1) {
	signed int i; // [esp+Ch] [ebp-4h]

	for ( i = 15; i > 11; --i ) {
		if ( ++a1[i] )
			break;
	}
}

void cc_aes_ctr(struct AES_ctx *ctx,uint8_t* buf, uint32_t length) {
	uintptr_t i;

	unsigned char s[16];
	memcpy(s,ctx->Iv,12);
	memset(&s[12],0,4);

	unsigned char tmp[16];
	memcpy(tmp,s,16);

	for (i = 0; i < length; i += AES_BLOCKLEN) {
		memcpy(s,tmp,16);
		incr_iv((unsigned __int8 *)s);
		memcpy(tmp,s,16);
		Cipher((state_t*)s,ctx->RoundKey);


		unsigned int max = 16;
		if ( i + 16 > length )
			max = length & 0xF;

		for(int j=0; j<max; j++)
			buf[i+j] = (buf[i+j] ^ s[j]);
	}
}

void Decrypt(const char *srcfile,const char *dstfile) {
	for(int i=0; i<256; i++)
		InvSubTable[SubTable[i]] = i;
	FILE *fp=fopen(srcfile,"rb");

	fseek(fp, 0, SEEK_END);
	unsigned int Len = ftell(fp);
	unsigned char *buf = (unsigned char *)malloc(Len);
	memset(buf, 0, Len);
	fseek(fp, 0, SEEK_SET);
	fread(buf, 1, Len, fp);
	fclose(fp);

	struct AES_ctx ctx;

	for(int i=0; i<Len; i+=0x200) {
		AES_init_ctx_iv(&ctx, AES_KEY, CTR_IV);
		cc_aes_ctr(&ctx,buf+i,(Len - i) > 0x200 ? 0x200: (Len-i));
	}

	for(int i=0; i<Len; i++) {
		buf[i] = InvSubTable[buf[i]];
	}

	FILE *fp2=fopen(dstfile,"wb");
	fwrite(buf,1,Len,fp2);
	fclose(fp2);

	free(buf);
	buf = NULL;
	return;
}

int main(void) {
	Decrypt("DSRD.enc","DSRD.dec");
}

 

암튼 그래서 거기에 복호화 로직이 있는걸 그대로 구현해서 DSRD.enc를 복호화 해보면,,,

오오 뭔가 나온다,, 같은 방식으로 EXM04B6Q.enc도 복호화 해보면,,,

분석했던 것처럼 압축파일이 나온다. 이걸 압축 풀어주고 다시 복호화를 해주면,,,

헤더처럼 보이는게 나오고,,,

binwalk 돌려보면 arm 인스트럭션이 잔뜩나온다!

 

오늘은 여기까지,,

댓글 남기기

이메일은 공개되지 않습니다.