C# :: Aufgabe #89

3 Lösungen Lösungen öffentlich

Verschlüsseln durch Verstecken

Fortgeschrittener - C# von eulerscheZhl - 27.02.2015 um 18:06 Uhr
Ein Teilgebiet der Kryptographie ist die Steganographie. Hier geht es darum Informationen so zu verstecken, dass andere gar nicht auf die Idee kommen, nach versteckten Informationen zu suchen.

Ein Beispiel, um eine Datei in einem Bild zu verstecken:
Erstelle ein Bytearray mit folgendem Inhalt: die ersten 4 Byte geben die Größe der versteckten Datei in Byte an (big Endian). Danach folgt der Dateiname in ASCII Codierung. Nach einem 0-Byte zu Trennung kommt die zu versteckende Datei selbst.
Diese Daten werden nun in einem Bild versteckt, indem die niederwertigsten beiden Bit eines Pixels für rot, grün und blau überschrieben werden, sodass in jedes Pixel 6 Bit passen. Es wird im oberen linken Eck gestartet und dann die Zeile aufgefüllt, anschließend in der nächsten Zeile fortgefahren.

Das Bild im Anhang wurde auf die beschriebene Weise manipuliert.
Schreibe ein Programm, das die versteckten Daten wieder sichtbar macht.

Lösungen:

vote_ok
von aheiland (650 Punkte) - 06.03.2015 um 16:02 Uhr
Quellcode ausblenden C#-Code
public class SteganographieReader
    {
        enum ColorCode {RED, GREEN, BLUE}
        private byte oneByte;
        private int byteFilled;
        private Queue<byte> byteCollection;
        private StringBuilder stringBuilder;

        public string filename
        {
            get
            {
                return stringBuilder.ToString();
            }
        }
        

        public void Read(string path)
        {
            collectByts(path);
            buildFilename();
        }

        private void collectByts(string path)
        {
            Bitmap image = new Bitmap(path);
            byteCollection = new Queue<byte>();
            resetByte();
            for (int y = 0; y < image.Height; y++)
            {
                for (int x = 0; x < image.Width; x++)
                {
                    Color pixel = image.GetPixel(x, y);
                    for (ColorCode c = ColorCode.RED; c <= ColorCode.BLUE; c++)
                    {
                        decodePixel(pixel, c);
                    }
                }
            }
        }

        private void decodePixel(Color pixel, ColorCode c)
        {
            oneByte = (byte)(oneByte << 2);
            switch (c)
            {
                case ColorCode.RED:
                    {
                        oneByte = (byte)(oneByte + (pixel.R & 3));
                        byteFilled = byteFilled + 2;
                        break;
                    }
                case ColorCode.GREEN:
                    {
                        oneByte = (byte)(oneByte + (pixel.G & 3));
                        byteFilled = byteFilled + 2;
                        break;
                    }
                case ColorCode.BLUE:
                    {
                        oneByte = (byte)(oneByte + (pixel.B & 3));
                        byteFilled = byteFilled + 2;
                        break;
                    }
            }
            if (byteFilled >= 8)
            {
                byteCollection.Enqueue(oneByte);
                resetByte();
            }

        }

        private void resetByte()
        {
            oneByte = 0;
            byteFilled = 0;
        }

        private void buildFilename()
        {
            stringBuilder = new StringBuilder();
            byteCollection.Dequeue();
            byteCollection.Dequeue();
            byteCollection.Dequeue();
            byteCollection.Dequeue();
            for (int i = 0; i < byteCollection.Count; i++)
            {
                byte b = byteCollection.Dequeue();
                if (b == 0) break;
                stringBuilder.Append((char)b);
            }
        }

        public void WriteToBaseDir(String dir)
        {
            byte[] byts = byteCollection.ToArray();
            File.Create(dir + filename).BeginWrite(byts,0,byts.Length,null,null);
        }
    }
2 Kommentare
vote_ok
von eulerscheZhl (5230 Punkte) - 06.03.2015 um 17:47 Uhr
Nachdem die erste Lösung eingereicht wurde, kommt hier meine.
Der Code ist übrigens auch im Bildanhang der Aufgabe versteckt.

Quellcode ausblenden C#-Code
using System;
using System.Drawing;
using System.IO;

namespace trainYourProgrammer
{
	class MainClass
	{
		public static void Main(string[] args) {
			string path = "/home/eulerschezahl/Dokumente/Programmieren/challenges/TrainYourProgrammer/";
			//einpacken
			HideFile ((Bitmap)Bitmap.FromFile (path + "Glueckwunsch_org.png"), 
			          new FileInfo (path + "TrainYourProgrammer.zip"))
				.Save(path + "Glueckwunsch.png");
			HideFile ((Bitmap)Bitmap.FromFile (path + "logo.png"), 
			          new FileInfo (path + "Glueckwunsch.png"))
				.Save(path + "Steganographie.png");

			//auspacken zur Probe
			ShowFile ((Bitmap)Bitmap.FromFile (path + "Steganographie.png"), path + "found/");
			ShowFile ((Bitmap)Bitmap.FromFile (path + "Glueckwunsch.png"), path + "found/");
		}

		public static Bitmap HideFile(Bitmap original, FileInfo file) {
			int size = (int)file.Length;
			if (original.Width * original.Height * 6 < (4 + file.Name.Length + 1 + file.Length) * 8)
				throw new NotSupportedException ("file too large for image");
			byte[] byte8 = new byte[4 + file.Name.Length + 1 + file.Length];
			byte8 [0] = (byte)(size >> 24);
			byte8 [1] = (byte)(size >> 16);
			byte8 [2] = (byte)(size >> 8);
			byte8 [3] = (byte)(size);
			for (int i = 0; i < file.Name.Length; i++)
				byte8[i + 4] = (byte)file.Name [i];
			byte[] data = File.ReadAllBytes (file.FullName);
			Array.Copy (data, 0, byte8, 5 + file.Name.Length, data.Length);
			byte[] byte6 = Byte8ToByte6 (byte8);
			Bitmap target = (Bitmap)original.Clone ();
			for (int i = 0; i < byte6.Length; i++) {
				int x = i % target.Width; 
				int y = i / target.Width;
				Color cl = target.GetPixel (x, y);
				cl = Color.FromArgb ((cl.R & 0xFC) | byte6[i] >> 4,
				                     (cl.G & 0xFC) | (byte6[i] >> 2) & 0x3,
				                     (cl.B & 0xFC) | byte6[i] & 0x3);
				target.SetPixel (x, y, cl);
			}
			return target;
		}

		public static void ShowFile(Bitmap bmp, string target) {
			byte[] byte6 = new byte[bmp.Width * bmp.Height];
			for (int i = 0; i < byte6.Length; i++) {
				int x = i % bmp.Width; 
				int y = i / bmp.Width;
				Color cl = bmp.GetPixel (x, y);
				byte6[i] = (byte)((cl.R & 0x3) << 4 | (cl.G & 0x3) << 2 | (cl.B & 0x3));
			}
			byte[] byte8 = Byte6ToByte8 (byte6);

			int size = byte8 [0] << 24 | byte8 [1] << 16 | byte8 [2] << 8 | byte8 [3];
			string filename = "";
			int index = 4;
			do {
				filename += (char)byte8 [index];
			} while (byte8[++index] != 0);
			byte[] file = new byte[size];
			Array.Copy (byte8, index + 1, file, 0, file.Length);
			File.WriteAllBytes (target + filename, file);
		}

		private static byte[] Byte8ToByte6(byte[] byte8) {
			Array.Resize (ref byte8, (byte8.Length / 3 + 2) * 3);
			byte[] byte6 = new byte[(byte8.Length * 4 + 2) / 3];
			for (int i = 0; i < byte8.Length / 3; i++) {
				byte6 [4 * i] = (byte)(byte8 [3 * i] >> 2);
				byte6 [4 * i + 1] = (byte)((byte8 [3 * i] << 4 | byte8 [3 * i + 1] >> 4) & 0x3F);
				byte6 [4 * i + 2] = (byte)((byte8 [3 * i + 1] << 2 | byte8[3*i + 2] >> 6) & 0x3F);
				byte6 [4 * i + 3] =(byte)( byte8 [3 * i + 2] & 0x3F);
			}
			return byte6;
		}

		private static byte[] Byte6ToByte8(byte[] byte6) {
			Array.Resize (ref byte6, (byte6.Length / 4 + 3) * 4);
			byte[] byte8 = new byte[(byte6.Length * 3 + 3) / 4];
			for (int i = 0; i < byte6.Length / 4; i++) {
				byte8 [3 * i] =(byte)( byte6 [4 * i] << 2 | byte6 [4 * i + 1] >> 4);
				byte8 [3 * i + 1] = (byte)(byte6 [4 * i + 1] << 4 | byte6 [4 * i + 2] >> 2);
				byte8 [3 * i + 2] = (byte)(byte6 [4 * i + 2] << 6 | byte6 [4 * i + 3]);
			}
			return byte8;
		}
	}
}
vote_ok
von hollst (13980 Punkte) - 27.07.2017 um 13:03 Uhr
Habe das Ganze einmal in eine WPF-GUI gepackt. Allerdings wird hier nicht ein Bild in einem Bild versteckt, sondern der Text der linken
Textbox (die "Geheimnachricht"). Das manipulierte Bild wird immer im File "hidden.bpm" abgelegt (im Ordner des Originalbildes) und stets ohne
Nachfrage überschrieben. Man sollte die Datei also umbenennen, wenn man das Bild weiter gebrauchen möchte. Das bmp-Format darf allerdings nicht in z. B. png-Format geändert werden. Dann sind die versteckten Informationen nicht mehr auffindbar.

Quellcode ausblenden C#-Code
using System;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.IO;

namespace aufgabe_89_wpf     {

    public partial class MainWindow : Window    {

        public MainWindow()        {
            InitializeComponent(); this.UpdateLabels();
        }

        #region some helper methods
        private static Microsoft.Win32.OpenFileDialog opendialog(string filter)        {
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            dlg.DefaultExt = ".png";
            dlg.Filter = filter + "all|*.*";
            return dlg;
        }

        private void UpdateLabels()        {
            this.lb_loaded_picture.Content  = 
                System.IO.Path.GetFileName(this.loaded_picture_file);
            this.lb_loaded_and_discovered_picture.Content   = 
                System.IO.Path.GetFileName(this.loaded_and_discovered_picture_file);
        }
        #endregion

        #region some global variables
        private static string NL = Environment.NewLine;

        private string loaded_picture_file                  = string.Empty;
        private string loaded_text_file                     = string.Empty;
        private string loaded_and_discovered_picture_file   = string.Empty;

        private bool bo_show_discovery_after_creation       = false;
        #endregion

        #region event handler
        private void bt_reset_Click(object sender, RoutedEventArgs e)
        {
            this.image_org.Source = null;
            this.image_hid.Source = null;
            this.tb_hide_info.Clear();
            this.tb_discovered_info.Clear();
            this.tb_helper_links.Clear();
            this.tb_helper_rechts.Clear();
            this.loaded_picture_file = string.Empty;
            this.loaded_text_file = string.Empty;
            this.loaded_and_discovered_picture_file = string.Empty;
            this.UpdateLabels();
        }

        private void bt_load_picture_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog dlg = opendialog("special graphics|*.bmp;*.jpg;*.jpeg;*.png|");
            if(dlg.ShowDialog() == true)            {
                string filename = dlg.FileName;
                this.loaded_picture_file = filename;
                this.UpdateLabels();

                BitmapImage bi = new BitmapImage(new Uri(filename));                
                this.image_org.Source = bi;                
            }
        }

        private void bt_hide_text_Click(object sender, RoutedEventArgs e)
        {
            if (this.loaded_picture_file == string.Empty)
                return;

            try            {
                BitmapImage bi = new BitmapImage(new Uri(this.loaded_picture_file));

                BitmapSource bitmapSource = new FormatConvertedBitmap(bi, PixelFormats.Default, null, 0);
                WriteableBitmap wbi = new WriteableBitmap(bitmapSource);

                int h = wbi.PixelHeight;
                int w = wbi.PixelWidth;
                int widthInByte = 4 * w;

                int[] pixelData = new int[w * h];
                wbi.CopyPixels(pixelData, widthInByte, 0);

                byte[] target = new byte[4 * w * h];
                for (var i = 0; i < pixelData.Length; i++)                {
                    Byte[] fourbytes = BitConverter.GetBytes(pixelData[i]);
                    fourbytes.CopyTo(target, 4 * i);
                }

                char[] chars = this.tb_hide_info.Text.ToCharArray();
                Encoding enc = Encoding.UTF8;// BigEndianUnicode;
                byte[] source = enc.GetBytes(chars);
                byte[] new_target = target.Hide(source);

                wbi.WritePixels(new Int32Rect(0, 0, w, h), new_target, widthInByte, 0);
                this.image_hid.Source = wbi;

                this.tb_helper_links.Text = new_target.ToMyString();

                byte[] hidden_txt = new_target.Discover();

                char[] hidden_chars = enc.GetChars(hidden_txt);
                string s = new string(hidden_chars);

                string hidden_file = System.IO.Path.GetDirectoryName(this.loaded_picture_file) + "\\hidden.bmp";
                this.loaded_and_discovered_picture_file = hidden_file;
                UpdateLabels();
                BitmapSource myBitmapImage = this.image_hid.Source as BitmapSource;

                if (File.Exists(hidden_file))
                    File.Delete(hidden_file);
                myBitmapImage.Save(hidden_file);

                if (bo_show_discovery_after_creation)
                    this.tb_discovered_info.Text = s;
            }
            catch (Exception ee)            {
                this.tb_discovered_info.Text = "not possible to save the file" + NL + NL + ee.Message;
            }
        }

        private void bt_load_text_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog dlg = opendialog("txt|*.txt|");
            if (dlg.ShowDialog() == true)
                this.tb_hide_info.Text = System.IO.File.ReadAllText(dlg.FileName);
        }

        private void bt_load_and_discover_picture_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog dlg = opendialog("graphics|*.bmp|");
            if (dlg.ShowDialog() == true)            {
                string filename = dlg.FileName;
                this.loaded_and_discovered_picture_file = filename;
                this.UpdateLabels();

                BitmapImage bi = new BitmapImage(new Uri(filename));
                this.image_hid.Source = bi;

                BitmapSource bitmapSource = new FormatConvertedBitmap(bi, PixelFormats.Default, null, 0);
                WriteableBitmap wbi = new WriteableBitmap(bitmapSource);

                int h = wbi.PixelHeight;
                int w = wbi.PixelWidth;
                int widthInByte = 4 * w;

                int[] pixelData = new int[w * h];
                wbi.CopyPixels(pixelData, widthInByte, 0);

                byte[] target = new byte[4 * w * h];
                for (var i = 0; i < pixelData.Length; i++)                {
                    Byte[] fourbytes = BitConverter.GetBytes(pixelData[i]);
                    fourbytes.CopyTo(target, 4 * i);
                }
                this.tb_helper_rechts.Text = target.ToMyString();                
                try                {
                    byte[] hidden_txt = target.Discover();

                    Encoding enc = Encoding.UTF8;
                    char[] hidden_chars = enc.GetChars(hidden_txt);
                    string s = new string(hidden_chars);

                    this.tb_discovered_info.Text = s;
                    this.UpdateLabels();
                }
                catch (Exception ee)                {
                    this.tb_discovered_info.Text = "no hidden infos discovered" + NL + NL + ee.Message;
                }
            }
        }
        #endregion
    }

    public static class Hide_and_Discover    {

        public static Byte[] Hide(this Byte[] hidden_place, Byte[] source)        {
            if (hidden_place.Length < 4 * (4 + source.Length))            {  //die ersten 16 Byte enthalten die arraylaenge von source
                MessageBox.Show("Inputerror Hide: " + hidden_place.Length.ToString() + " " + source.Length.ToString());
                return hidden_place;
            }

            Byte[] first4_source = BitConverter.GetBytes(source.Length);
            Byte[][] targets = hidden_place.Splitt(4 * first4_source.Length);

            targets[0] = BytesIntoBytes(targets[0], first4_source);
            targets[1] = BytesIntoBytes(targets[1], source);
            return targets.Join();
        }

        public static Byte[] Discover(this Byte[] source)        {

            Byte[] first16 = source.GetSubArray(anzahl: 16);
            Byte[][] bint = new Byte[4][];
            for (var i = 0; i < 4; i++)            {
                bint[i] = new Byte[4];
                for (var j = 0; j < 4; j++)
                    bint[i][j] = first16[4 * i + j];
            }
            Byte[] forint = new Byte[4];
            for (var i = 0; i < 4; i++)
                forint[i] = bint[i].From4();

            forint.Reverse();
            int size = BitConverter.ToInt32(forint, 0);

            Byte[] result = new Byte[size];
            int zeiger = 16;
            for (var i = 0; i < size; i++)            {
                Byte[] next4 = source.GetSubArray(ab: zeiger, anzahl: 4);
                result[i] = next4.From4();
                zeiger += 4;
            }
            return result;
        }

        private static Byte[] BytesIntoBytes(this Byte[] hidden_place, Byte[] source)        {

            Byte[] result = new Byte[hidden_place.Length];
            hidden_place.CopyTo(result, 0);

            Byte eliminate_last_two = 0xFC;
            Byte[] filter = new Byte[] { 0x03, 0x0C, 0x30, 0xC0 };

            int counter = 0;
            for (var i = 0; i < source.Length; i++)            {
                Byte b = source[i];
                for (Byte j = 0; j < filter.Length; j++)                {
                    Byte bs = (Byte)(((Byte)(b & filter[j])) >> (2 * j));
                    result[counter] = (Byte)((Byte)(result[counter] & eliminate_last_two) ^ bs);
                    counter++;
                }
            }
            return result;
        }

        private static Byte[][] Splitt(this Byte[] b, int ab)        {
            Byte[][] result = new Byte[2][];
            result[0] = new Byte[ab];
            for (var i = 0; i < result[0].Length; i++)
                result[0][i] = b[i];
            result[1] = new Byte[b.Length - ab];
            for (var i = 0; i < result[1].Length; i++)
                result[1][i] = b[i + ab];
            return result;
        }

        private static Byte[] Join(this Byte[][] b)        {
            Byte[] result = new Byte[b[0].Length + b[1].Length];
            b[0].CopyTo(result, 0);
            b[1].CopyTo(result, b[0].Length);
            return result;
        }

        private static Byte From4(this Byte[] b)        {
            Byte maske = 0x03, result = 0x00;
            for (var i = 0; i < b.Length; i++)            {
                Byte value = (Byte)((b[i] & maske) << 2 * i);
                result = (Byte)(result ^ value);
            }
            return result;
        }

        private static Byte[] GetSubArray(this Byte[] b, int ab = 0, int anzahl = 1)        {
            Byte[] result = new Byte[anzahl];
            for (var i = 0; i < anzahl; i++)
                result[i] = b[i + ab];
            return result;
        }
    }

    public static class MyExtensions    {

        public static string ToMyString(this byte[] b)        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(b.Length.ToString("n0"));
            for (var i = 0; i < b.Length; i++)            {
                if (i % 16 == 0)
                    sb.AppendLine();
                sb.Append(String.Format("{0:X2} ", b[i]));
            }
            return sb.ToString();
        }

        public static void Save(this BitmapSource image, string filePath)        {
            BitmapEncoder encoder = new BmpBitmapEncoder();// PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(image));
            using (var fileStream = new System.IO.FileStream(filePath, System.IO.FileMode.Create))            {
                encoder.Save(fileStream);
            }
        }
    }
}

Quellcode ausblenden C#-Code
<Window x:Class="aufgabe_89_wpf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:aufgabe_89_wpf"
        mc:Ignorable="d"
        Title="hide and discover demo" Height="600" Width="970" FontFamily="Courier New" Background="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" WindowState="Maximized">
    <Grid>
        <TabControl VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" TabStripPlacement="Bottom">
            <TabItem Header=" main ">
                <Grid x:Name="grid_tab_0" Margin="0,3,0,0" Background="{DynamicResource {x:Static SystemColors.GradientInactiveCaptionBrushKey}}">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="1*"/>
                        <ColumnDefinition Width="1*"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="45"/>
                        <RowDefinition Height="1*"/>
                        <RowDefinition Height="1*"/>
                        <RowDefinition Height="45"/>
                    </Grid.RowDefinitions>
                    <GridSplitter Grid.Column="1" HorizontalAlignment="Left" Margin="0,10" Grid.Row="1" Grid.RowSpan="3" Width="5"/>
                    <GridSplitter Grid.Row="1" ResizeDirection="Rows" HorizontalAlignment="Stretch" Height="5" VerticalAlignment="Bottom" Grid.ColumnSpan="2"/>
                    <Image x:Name="image_org" Margin="10" Grid.Row="1"/>
                    <Image x:Name="image_hid" Margin="10" Grid.Row="1" Grid.Column="1"/>
                    <StackPanel Margin="5,15,5,5" Orientation="Horizontal">
                        <Button x:Name="bt_reset" Content=" reset " HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10,0,25,0" Click="bt_reset_Click"/>

                        <Button x:Name="bt_load_picture" Content=" load picture " HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10,0,0,0" Click="bt_load_picture_Click"/>
                        <Button x:Name="bt_load_text" Content=" load text " HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10,0,0,0" Click="bt_load_text_Click"/>
                        <Button x:Name="bt_hide_text" Content=" hide text from textbox " HorizontalAlignment="Center" VerticalAlignment="Center" Margin="50,0,0,0" Click="bt_hide_text_Click"/>
                    </StackPanel>
                    <StackPanel Margin="5,15,5,5" Orientation="Horizontal" Grid.Column="1">
                        <Button x:Name="bt_load_and_discover_picture" Content=" load picture and discover into textbox " HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10,0,0,0" Click="bt_load_and_discover_picture_Click" />
                    </StackPanel>
                    <GroupBox Header=" hide information " Margin="5" Grid.Row="2" Background="{DynamicResource {x:Static SystemColors.ActiveCaptionBrushKey}}" BorderThickness="1,0,1,1" Foreground="#FFDE2020" Grid.RowSpan="1" BorderBrush="#FF171819">
                        <TextBox x:Name="tb_hide_info" Margin="5" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" AcceptsReturn="True" AcceptsTab="True"/>
                    </GroupBox>
                    <GroupBox Header=" discovered information " Margin="5" Grid.Column="1" Grid.Row="2" Background="{DynamicResource {x:Static SystemColors.ActiveCaptionBrushKey}}" BorderThickness="1,0,1,1" Foreground="#FFDE2020" Grid.RowSpan="1">
                        <TextBox x:Name="tb_discovered_info" Margin="5" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" AcceptsReturn="True" AcceptsTab="True"/>
                    </GroupBox>
                    <Label x:Name="lb_loaded_picture" Content="Label" Margin="10,0,0,0" Grid.Row="3" VerticalAlignment="Center"/>
                    <Label x:Name="lb_loaded_and_discovered_picture" Content="Label" Margin="10,0,0,0" Grid.Row="3" Grid.Column="1" VerticalAlignment="Center"/>
                </Grid>
            </TabItem>
            <TabItem Header=" extra text ">
                <Grid x:Name="grid_tab_1">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="1*"/>
                        <ColumnDefinition Width="1*"/>
                    </Grid.ColumnDefinitions>
                    <TextBox x:Name="tb_helper_links" Margin="5" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" AcceptsReturn="True" AcceptsTab="True" />
                    <TextBox x:Name="tb_helper_rechts" Margin="5" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" AcceptsReturn="True" AcceptsTab="True" Grid.Column="1"/>
                </Grid>
            </TabItem>
        </TabControl>
    </Grid>
</Window>

2101598

Du scheinst einen AdBlocker zu nutzen. Ich würde mich freuen, wenn du ihn auf dieser Seite deaktivierst und dich davon überzeugst, dass die Werbung hier nicht störend ist.