GIF တွင် Steganography

နိဒါန်း

မေတ္တာနှင့်ကြားလိုက်ပါ၏။
မကြာသေးမီက တက္ကသိုလ်တွင် ပညာသင်ကြားနေစဉ် “သတင်းအချက်အလက် လုံခြုံရေးဆိုင်ရာ ဆော့ဖ်ဝဲလ်နည်းလမ်းများ” တွင် သင်တန်းတစ်ခုရှိခဲ့ပါသည်။ တာဝန်က GIF ဖိုင်များတွင် မက်ဆေ့ချ်ထည့်သည့် ပရိုဂရမ်တစ်ခုကို ဖန်တီးရန် ကျွန်ုပ်တို့ကို လိုအပ်သည်။ Java မှာလုပ်ဖို့ဆုံးဖြတ်လိုက်တယ်။

ဒီဆောင်းပါးမှာ သီအိုရီဆိုင်ရာ အချက်အချို့အပြင် ဒီပရိုဂရမ်လေးကို ဘယ်လိုဖန်တီးခဲ့သလဲဆိုတာကို ဖော်ပြပါမယ်။

အဆိုပါသီအိုရီတစ်စိတ်တစ်ပိုင်း

GIF ဖော်မတ်

GIF (ဂရပ်ဖစ်ဖလှယ်မှုဖော်မတ် - ပုံများဖလှယ်သည့်ဖော်မတ်) သည် အရောင် 256 ရောင်အထိ ဖော်မတ်ဖြင့် အရည်အသွေးမဆုံးရှုံးဘဲ ချုံ့ထားသောဒေတာကို သိမ်းဆည်းနိုင်သည့် ဂရပ်ဖစ်ပုံများကို သိမ်းဆည်းရန်အတွက် ဖော်မတ်တစ်ခုဖြစ်သည်။ ဤဖော်မတ်ကို 1987 (GIF87a) တွင် CompuServe မှ ကွန်ရက်များပေါ်တွင် raster ပုံများကို ထုတ်လွှင့်ရန်အတွက် တီထွင်ခဲ့သည်။ 1989 ခုနှစ်တွင်၊ ဖော်မတ် (GIF89a) ကို မွမ်းမံခဲ့ပြီး၊ ပွင့်လင်းမြင်သာမှုနှင့် ကာတွန်းအတွက် ပံ့ပိုးမှုကို ထည့်သွင်းခဲ့သည်။

GIF ဖိုင်များတွင် ပိတ်ဆို့ဖွဲ့စည်းပုံ ရှိသည်။ ဤဘလောက်များသည် ပုံသေအရှည်တစ်ခုအမြဲရှိပါသည် (သို့မဟုတ် အချို့သောအလံများပေါ်တွင်မူတည်သည်) ထို့ကြောင့် ဘလောက်တစ်ခုစီတည်ရှိသည့်နေရာနှင့်ပတ်သက်၍ အမှားလုပ်ရန်မဖြစ်နိုင်ပေ။ GIF89a ဖော်မတ်ရှိ အရိုးရှင်းဆုံး ကာတွန်းမဟုတ်သော GIF ရုပ်ပုံ၏ ဖွဲ့စည်းပုံ-

GIF တွင် Steganography

ဖွဲ့စည်းတည်ဆောက်ပုံတုံးများအားလုံး၏ ဤအခြေအနေတွင်၊ ကျွန်ုပ်တို့သည် ကမ္ဘာလုံးဆိုင်ရာ ပျဉ်ချပ်တုံးနှင့် palette အတွက် တာဝန်ရှိသော ဘောင်များကို စိတ်ဝင်စားပါမည်-

  • CT - ကမ္ဘာလုံးဆိုင်ရာ ပျဉ်ချပ်တစ်ခု ရှိနေခြင်း။ ဤအလံကို သတ်မှတ်ပါက၊ ကမ္ဘာလုံးဆိုင်ရာ palette သည် ယုတ္တိဖန်သားပြင် ကိုင်တွယ်ပြီးနောက် ချက်ချင်းစတင်ရပါမည်။
  • Size - ပုံတွင်ပါရှိသောအရောင်များနှင့် palette အရွယ်အစား။ ဤကန့်သတ်ချက်အတွက် တန်ဖိုးများ-

အရွယ်
အရောင်အရေအတွက်
ပျဉ်ချပ်အရွယ်အစား၊ ဘိုက်များ

7
256
768

6
128
384

5
64
192

4
32
96

3
16
48

2
8
24

1
4
12

0
2
6

ကုဒ်ဝှက်နည်းများ

ပုံဖိုင်များတွင် စာဝှက်ရန် အောက်ပါနည်းလမ်းများကို အသုံးပြုပါမည်။

  • LSB (Least Significant Bit) နည်းလမ်း
  • Palette ပေါင်းထည့်နည်း

LSB နည်းလမ်း - ယေဘူယျပုံသေနည်း။ ၎င်းတွင် ကွန်တိန်နာရှိ နောက်ဆုံးသိသာထင်ရှားသော bit များ (ကျွန်ုပ်တို့ကိစ္စတွင်၊ ကမ္ဘာလုံးဆိုင်ရာ palette bytes) ကို ဝှက်ထားသောစာ၏ bits များဖြင့် အစားထိုးခြင်း ပါဝင်သည်။

ပရိုဂရမ်သည် ဤနည်းလမ်း၏ တစ်စိတ်တစ်ပိုင်းအဖြစ် ကမ္ဘာလုံးဆိုင်ရာ palette bytes အတွင်းရှိ နောက်ဆုံးဘစ်နှစ်ခုကို အသုံးပြုမည်ဖြစ်သည်။ ဆိုလိုသည်မှာ 24-bit ရုပ်ပုံတစ်ပုံအတွက် palette အရောင်သည် အနီ၊ အပြာနှင့် အစိမ်းအတွက် သုံးဘိုက်ရှိရာ၊ ၎င်းတွင် မက်ဆေ့ချ်တစ်ခုကို ထည့်သွင်းပြီးနောက်၊ အရောင်အစိတ်အပိုင်းတစ်ခုစီသည် အများဆုံး 3/255 အဆင့်အထိ ပြောင်းလဲသွားမည်ဖြစ်သည်။ ထိုသို့သောပြောင်းလဲမှုကို ပထမဦးစွာ လူသားမျက်စိဖြင့် မမြင်နိုင်သော သို့မဟုတ် သတိပြုမိရန် ခက်ခဲမည်ဖြစ်ပြီး၊ ဒုတိယအချက်မှာ အရည်အသွေးနိမ့်သော သတင်းထွက်ရှိကိရိယာများတွင် ၎င်းကို မြင်နိုင်မည်မဟုတ်ပေ။

အချက်အလက်ပမာဏသည် ပုံ palette ၏ အရွယ်အစားပေါ်တွင် တိုက်ရိုက်မူတည်ပါမည်။ ပျဉ်ချပ်၏ အမြင့်ဆုံးအရွယ်အစားမှာ အရောင် 256 ရောင်ဖြစ်ပြီး အရောင်တစ်ခုစီ၏ အစိတ်အပိုင်းတစ်ခုစီတွင် မက်ဆေ့ချ်နှစ်ခုကို ရေးထားပါက၊ အမြင့်ဆုံးမက်ဆေ့ခ်ျအရှည် (ပုံတွင် အများဆုံး palette ပါရှိသော) သည် 192 bytes ဖြစ်သည်။ မက်ဆေ့ချ်ကို ပုံတွင် ထည့်သွင်းပြီးသည်နှင့်၊ ဖိုင်အရွယ်အစား မပြောင်းလဲပါ။

Palette ချဲ့နည်းGIF ဖွဲ့စည်းပုံအတွက်သာ အလုပ်လုပ်သည်။ သေးငယ်တဲ့ palette ပါတဲ့ ပုံတွေပေါ်မှာ အထိရောက်ဆုံးဖြစ်ပါလိမ့်မယ်။ ၎င်း၏ အနှစ်သာရမှာ ၎င်းသည် palette ၏ အရွယ်အစားကို တိုးစေပြီး ရောင်စုံဘိုက်များအစား လိုအပ်သော ဘိုက်များကို ရေးသားရန် ထပ်လောင်းနေရာ ပေးဆောင်ရခြင်း ဖြစ်သည်။ ပျဉ်ချပ်၏ အနိမ့်ဆုံးအရွယ်အစားသည် အရောင် 2 ရောင် (6 bytes) ဟု ယူဆပါက၊ ထည့်သွင်းထားသော မက်ဆေ့ချ်၏ အများဆုံးအရွယ်အစားမှာ 256 × 3–6 = 762 bytes ဖြစ်နိုင်ပါသည်။ အားနည်းချက်မှာ ကုဒ်ဝှက်စနစ် လုံခြုံမှု နည်းပါးသည်၊ မက်ဆေ့ချ်ကို ထပ်လောင်း ကုဒ်ဝှက်ခြင်း မပြုပါက မည်သည့် စာသားတည်းဖြတ်မှုမဆို အသုံးပြု၍ ထည့်သွင်းထားသော မက်ဆေ့ချ်ကို ဖတ်နိုင်ပါသည်။

လက်တွေ့တစ်စိတ်တစ်ဒေသ

အစီအစဉ်ဒီဇိုင်း

ကုဒ်ဝှက်ခြင်းနှင့် ကုဒ်ဝှက်ခြင်းဆိုင်ရာ အယ်လဂိုရီသမ်များကို အကောင်အထည်ဖော်ရန်အတွက် လိုအပ်သောကိရိယာများအားလုံးကို ပက်ကေ့ဂျ်တွင် ထည့်သွင်းပါမည်။ com.tsarik.steganography. ဤအထုပ်တွင် အင်တာဖေ့စ်ပါဝင်သည်။ Encryptor နည်းလမ်းများဖြင့် encrypt и decrypt၊အတန်း Binarybit arrays များအပြင် exception classes များဖြင့် အလုပ်လုပ်နိုင်စွမ်းကို ပံ့ပိုးပေးသော၊ UnableToEncryptException и UnableToDecryptExceptionအင်တာဖေ့စ်နည်းလမ်းများတွင် အသုံးပြုသင့်သည်။ Encryptor encoding နှင့် decoding error အသီးသီးရှိလျှင်။

ပင်မအစီအစဉ်အထုပ် com.tsarik.programs.gifed static method ဖြင့် runnable program class တစ်ခု ပါဝင်သည်။ mainပရိုဂရမ်ကို run ရန်ခွင့်ပြုသည်။ ပရိုဂရမ်ဘောင်များကို သိမ်းဆည်းသည့် အတန်းအစား၊ အခြားအတန်းများနှင့်အတူ packages များ။

အယ်လဂိုရီသမ်များ အကောင်အထည်ဖော်မှုကို အထုပ်တွင် တင်ပြပါမည်။ com.tsarik.programs.gifed.gif အတန်းများ GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod. ဤအတန်းနှစ်ခုစလုံးသည် interface ကိုအကောင်အထည်ဖော်လိမ့်မည်။ Encryptor.

GIF ဖော်မတ်၏ တည်ဆောက်ပုံအပေါ် အခြေခံ၍ သင်သည် ရုပ်ပုံ palette သို့ မက်ဆေ့ချ်တစ်ခုကို မိတ်ဆက်ရန်အတွက် ယေဘူယျ အယ်လဂိုရီသမ်တစ်ခုကို ဖန်တီးနိုင်သည်-

GIF တွင် Steganography

ပုံတစ်ပုံတွင် မက်ဆေ့ချ်တစ်ခု ရှိနေခြင်းကို ဆုံးဖြတ်ရန်၊ ကုဒ်ဒါသည် ဦးစွာဖတ်ပြီး မှန်ကန်မှု ရှိမရှိ စစ်ဆေးပေးသည့် မက်ဆေ့ချ်၏ အစတွင် အချို့သော အစီအစဥ်တစ်ခုကို ပေါင်းထည့်ရန် လိုအပ်ပါသည်။ မကိုက်ညီပါက ပုံတွင် ဝှက်ထားသော မက်ဆေ့ချ်မရှိဟု ယူဆပါသည်။ နောက်တစ်ခုကတော့ မက်ဆေ့ခ်ျရဲ့ အရှည်ကို သတ်မှတ်ရပါမယ်။ အဲဒီအခါမှာ မက်ဆေ့ခ်ျရဲ့ စာသားက သူ့ဟာသူ။

အပလီကေးရှင်းတစ်ခုလုံး၏ Class diagram-

GIF တွင် Steganography

အစီအစဉ်ကို အကောင်အထည်ဖော်ခြင်း။

ပရိုဂရမ်တစ်ခုလုံး၏အကောင်အထည်ဖော်မှုကို အစိတ်အပိုင်းနှစ်ခုအဖြစ် ပိုင်းခြားနိုင်သည်- အင်တာဖေ့စ်ကုဒ်ဝှက်ခြင်းနှင့် စာဝှက်ခြင်းနည်းလမ်းများကို အကောင်အထည်ဖော်ခြင်း။ Encryptorအတန်းထဲတွင်၊ GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethodနှင့် user interface ၏အကောင်အထည်ဖော်မှု။

အတန်းကို ဆင်ခြင်ပါ။ GIFEncryptorByLSBMethod.

GIF တွင် Steganography

Fields firstLSBit и secondLSBit ပုံတစ်ပုံချင်းစီ၏ byte တစ်ခုစီ၏ bits နံပါတ်များပါရှိပြီး မက်ဆေ့ချ်ထည့်သင့်သည့်နေရာမှ မက်ဆေ့ချ်ကို ဖတ်သင့်သည်။ လယ်ကွင်း checkSequence ထည့်သွင်းထားသော မက်ဆေ့ဂျ်ကို အသိအမှတ်ပြုကြောင်း သေချာစေရန် check bit sequence ကို သိမ်းဆည်းပါ။ အငြိမ်နည်းလမ်း getEncryptingFileParameters သတ်မှတ်ထားသောဖိုင်၏ ကန့်သတ်ချက်များနှင့် ဖြစ်နိုင်ချေရှိသော မက်ဆေ့ချ်၏ ဝိသေသလက္ခဏာများကို ပြန်ပေးသည်။

နည်းလမ်း algorithm encrypt класса GIFEncryptorByLSBMethod:

GIF တွင် Steganography

ပြီးတော့ သူ့ကုဒ်

@Override
public void encrypt(File in, File out, String text) throws UnableToEncodeException, NullPointerException, IOException {
	if (in == null) {
		throw new NullPointerException("Input file is null");
	}
	if (out == null) {
		throw new NullPointerException("Output file is null");
	}
	if (text == null) {
		throw new NullPointerException("Text is null");
	}
	
	// read bytes from input file
	byte[] bytes = new byte[(int)in.length()];
	InputStream is = new FileInputStream(in);
	is.read(bytes);
	is.close();
	
	// check format
	if (!(new String(bytes, 0, 6)).equals("GIF89a")) {
		throw new UnableToEncodeException("Input file has wrong GIF format");
	}
	
	// read palette size property from first three bits in the 10-th byte from the file
	byte[] b10 = Binary.toBitArray(bytes[10]);
	byte bsize = Binary.toByte(new byte[] {b10[0], b10[1], b10[2]});
	
	// calculate color count and possible message length
	int bOrigColorCount = (int)Math.pow(2, bsize+1);
	int possibleMessageLength = bOrigColorCount*3/4;
	int possibleTextLength = possibleMessageLength-2;// one byte for check and one byte for message length
	
	if (possibleTextLength < text.length()) {
		throw new UnableToEncodeException("Text is too big");
	}
	
	int n = 13;
	
	// write check sequence
	for (int i = 0; i < checkSequence.length/2; i++) {
		byte[] ba = Binary.toBitArray(bytes[n]);
		ba[firstLSBit] = checkSequence[2*i];
		ba[secondLSBit] = checkSequence[2*i+1];
		bytes[n] = Binary.toByte(ba);
		n++;
	}
	
	// write text length
	byte[] cl = Binary.toBitArray((byte)text.length());
	for (int i = 0; i < cl.length/2; i++) {
		byte[] ba = Binary.toBitArray(bytes[n]);
		ba[firstLSBit] = cl[2*i];
		ba[secondLSBit] = cl[2*i+1];
		bytes[n] = Binary.toByte(ba);
		n++;
	}
	
	// write message
	byte[] textBytes = text.getBytes();
	for (int i = 0; i < textBytes.length; i++) {
		byte[] c = Binary.toBitArray(textBytes[i]);
		for (int ci = 0; ci < c.length/2; ci++) {
			byte[] ba = Binary.toBitArray(bytes[n]);
			ba[firstLSBit] = c[2*ci];
			ba[secondLSBit] = c[2*ci+1];
			bytes[n] = Binary.toByte(ba);
			n++;
		}
	}
	
	// write output file
	OutputStream os = new FileOutputStream(out);
	os.write(bytes);
	os.close();
}

နည်းလမ်း၏ အယ်လဂိုရီသမ်နှင့် အရင်းအမြစ်ကုဒ် decrypt класса GIFEncryptorByLSBMethod:

GIF တွင် Steganography

@Override
public String decrypt(File in) throws UnableToDecodeException, NullPointerException, IOException {
	if (in == null) {
		throw new NullPointerException("Input file is null");
	}
	
	// read bytes from input file
	byte[] bytes = new byte[(int)in.length()];
	InputStream is = new FileInputStream(in);
	is.read(bytes);
	is.close();
	
	// check format
	if (!(new String(bytes, 0, 6)).equals("GIF89a")) {
		throw new UnableToDecodeException("Input file has wrong GIF format");
	}
	
	// read palette size property from first three bits in the 10-th byte from the file
	byte[] b10 = Binary.toBitArray(bytes[10]);
	byte bsize = Binary.toByte(new byte[] {b10[0], b10[1], b10[2]});
	
	// calculate color count and possible message length
	int bOrigColorCount = (int)Math.pow(2, bsize+1);
	int possibleMessageLength = bOrigColorCount*3/4;
	int possibleTextLength = possibleMessageLength-2;	// one byte for check and one byte for message length
	
	int n = 13;
	
	// read check sequence
	byte[] csBits = new byte[checkSequence.length];
	for (int i = 0; i < 4; i++) {
		byte[] ba = Binary.toBitArray(bytes[n]);
		csBits[2*i] = ba[firstLSBit];
		csBits[2*i+1] = ba[secondLSBit];
		n++;
	}
	byte cs = Binary.toByte(csBits);
	
	if (cs != Binary.toByte(checkSequence)) {
		throw new UnableToDecodeException("There is no encrypted message in the image (Check sequence is incorrect)");
	}
	
	// read text length
	byte[] cl = new byte[8];
	for (int i = 0; i < 4; i++) {
		byte[] ba = Binary.toBitArray(bytes[n]);
		cl[2*i] = ba[firstLSBit];
		cl[2*i+1] = ba[secondLSBit];
		n++;
	}
	byte textLength = Binary.toByte(cl);
	
	if (textLength < 0) {
		throw new UnableToDecodeException("Decoded text length is less than 0");
	}
	if (possibleTextLength < textLength) {
		throw new UnableToDecodeException("There is no messages (Decoded message length (" + textLength + ") is less than Possible message length (" + possibleTextLength + "))");
	}
	
	// read text bits and make text bytes
	byte[] bt = new byte[textLength];
	for (int i = 0; i < bt.length; i++) {
		byte[] bc = new byte[8];
		for (int bci = 0; bci < bc.length/2; bci++) {
			byte[] ba = Binary.toBitArray(bytes[n]);
			bc[2*bci] = ba[firstLSBit];
			bc[2*bci+1] = ba[secondLSBit];
			n++;
		}
		bt[i] = Binary.toByte(bc);
	}
	
	return new String(bt);
}

အတန်း၏အကောင်အထည်ဖော်မှု GIFEncryptorByPaletteExtensionMethod အလားတူဖြစ်မည်၊ အချက်အလက်သိမ်းဆည်းခြင်း/ဖတ်ရှုခြင်းနည်းလမ်းသာလျှင် ကွဲပြားပါသည်။

အတန်းထဲမှာ MainFrame wrapper နည်းလမ်းများကို ဖော်ပြထားပါသည်။ encryptImage(Encryptor encryptor) и decryptImage(Encryptor encryptor)ကြားခံနည်းလမ်းများ၏ ရလဒ်များကို လုပ်ဆောင်ခြင်း။ Encryptor အသုံးပြုသူနှင့် အပြန်အလှန် ဆက်ဆံခြင်း၊ ဆိုလိုသည်မှာ ဖိုင်ရွေးချယ်မှု ဒိုင်ယာလော့ခ်ကို ဖွင့်ခြင်း၊ အမှားအယွင်း မက်ဆေ့ချ်များ ပြသခြင်း စသည်ဖြင့်၊ အခြားနည်းလမ်းများအပြင် openImage()အသုံးပြုသူကို ပုံတစ်ပုံရွေးချယ်ခွင့်ပေးခြင်း၊ exit()အပလီကေးရှင်းမှ ထွက်သော၊ ဤနည်းများကို မှည့်ခေါ်သည်။ Actionသက်ဆိုင်သော မီနူး ပစ္စည်းများ။ ဤအတန်းသည် အရန်နည်းလမ်းများကို ထပ်လောင်းလုပ်ဆောင်သည်- createComponents() - ပုံစံ အစိတ်အပိုင်းများ ဖန်တီးခြင်း၊ loadImageFile(File f) — ဖိုင်တစ်ခုမှ အထူးအစိတ်အပိုင်းတစ်ခုသို့ ပုံတစ်ခုကို တင်ခြင်း။ အတန်း၏အကောင်အထည်ဖော်မှု GIFEncryptorByPaletteExtensionMethod class implementation နဲ့ ဆင်တူပါတယ်။ GIFEncryptorByLSBMethodအဓိကကွာခြားချက်မှာ palette မှ message bytes များကို ရေးသားခြင်းနှင့် ဖတ်ခြင်းတွင်ဖြစ်သည်။

ပရိုဂရမ်လည်ပတ်မှု

LBS နည်းလမ်း

ဒီလိုပုံလေးရှိတယ်ဆိုပါစို့။

GIF တွင် Steganography

ဤပုံတွင်၊ palette တွင် အရောင် 256 ရောင် (Paint save as) ပါဝင်ပါသည်။ ပထမအရောင်လေးမျိုးကတော့ အဖြူ၊ အနက်၊ အနီ၊ အစိမ်း။ အခြားအရောင်များမှာ အနက်ရောင်ဖြစ်သည်။ global palette bit sequence သည် အောက်ပါအတိုင်း ဖြစ်လိမ့်မည် ။

11111111 11111111 11111111 00000000 00000000 00000000 11111111 00000000 00000000 00000000 11111111 00000000...

GIF တွင် Steganography

မက်ဆေ့ဂျ်ကို ထည့်သွင်းပြီးသည်နှင့်၊ မျဉ်းသားထားသော ဘစ်များကို မက်ဆေ့ချ်မှ ဘစ်များဖြင့် အစားထိုးမည်ဖြစ်သည်။ ရလာတဲ့ပုံက မူရင်းပုံနဲ့ လုံးဝမတူပါဘူး။

မူရင်း
ထည့်သွင်းထားသော မက်ဆေ့ဂျ်နှင့်အတူ ပုံ

GIF တွင် Steganography
GIF တွင် Steganography

Palette ချဲ့နည်း

ဤနည်းလမ်းကို အသုံးပြု၍ မက်ဆေ့ချ်ပါရှိသော ပုံတစ်ပုံကို သင်ဖွင့်သောအခါတွင် အောက်ပါပုံကို သင်တွေ့မြင်ရလိမ့်မည်-

GIF တွင် Steganography

ဤနည်းလမ်းသည် ပြီးပြည့်စုံသော သူလျှိုလှုပ်ရှားမှုများအတွက် အလုပ်မဖြစ်နိုင်ကြောင်းနှင့် မက်ဆေ့ချ်၏ ထပ်လောင်းကုဒ်ဝှက်ခြင်း လိုအပ်နိုင်သည် ထင်ရှားပါသည်။

ကာတွန်းရုပ်ပုံများတွင် ကုဒ်ဝှက်ခြင်း/စာဝှက်ခြင်း သည် ပုံမှန် ပုံသဏ္ဍာန်ပုံများကဲ့သို့ အလုပ်လုပ်သော်လည်း ကာတွန်းရုပ်ပုံများသည် ပျက်မသွားပါ။

အသုံးပြုထားသော အရင်းအမြစ်များ-

ဒေါင်းလုပ်:

source: www.habr.com

DDoS ကာကွယ်ရေး၊ VPS VDS ဆာဗာများပါသည့် ဆိုက်များအတွက် ယုံကြည်စိတ်ချရသော hosting ကို ဝယ်ယူပါ။ 🔥 DDoS ကာကွယ်မှု၊ VPS VDS ဆာဗာများပါရှိသော ယုံကြည်စိတ်ချရသော ဝဘ်ဆိုက် hosting ကို ဝယ်ယူပါ | ProHoster