DCSIMG
March 2012 - Posts - שלמה גולדברג (הרב דוטנט)

שלמה גולדברג (הרב דוטנט)

מרצה בסלע ויועץ בעולם ה - net.

March 2012 - Posts

עצלנות של מפתחים ואבטחת מידע - והפעם כיצד לעקוף את הבדיקה שטלריק עושים האם קניתם את המוצר (2)

 

אני יודע שהפוסטים הללו לא בהכרח קשורים כך כך לאבטחת מידע - אבל בעקיפין אם נכתוב קוד לא נכון שניתן לכתוב קוד שיעקוף אותו סביר להניח שזה יכול גם לגרום לבעיות באבטחת מידע.
 
באחד הפוסטים סיפרתי כיצד לעקוף את ההודעה המעצבנת של טלריק בזמן פיתוח אם אין לכם רישיון, בפוסט זה אני אראה כיצד לעקוף אותם בחבילה שלהם לעולם ה - Windows Forms.
 
 
רק להבהיר שחלילה לגנוב מהם, ותמיד כשאני מעלה מוצר לאויר שמשתמש בטלריק אני דואג שיהיה רשיון, המטרה בפוסט היא לבהיר כיצד ניתן לכתוב קוד גרוע - (וגם איך לעשות לנו כמפתחים חיים קלים יותר בשלב הפיתוח - וכמובן איזה כיף שיש Reflector).
 
 
אז ככה, במידה ויש לכם את החבילה לעולם ה - Windows forms, סביר להניח שמידי פעם הייתם מקבלים את החלון הבא:
 
telerik win fors
 
 
האמת שזה ממש מעצבן, אז כרגיל פתחתי את ה - Reflector והתחלתי לשוטט - הפעם לקח לי הרבה יותר זמן מהרגיל, כעבור שלוש שעות שיטוט ב - Reflector מצאתי את הקוד הבא באובייקט שנקרא RadElementTree.
 
 

private void CheckLicense()

{

    if ((RadControl.licenseCount == -1) && (numberOfEvalMsgsShown < 3))

    {

        RadControl.licenseCount = new Random().Next(0, 10);

        if (RadControl.licenseCount == 1)

        {

            Assembly assembly = null;

            foreach (Assembly assembly2 in AppDomain.CurrentDomain.GetAssemblies())

            {

                if (assembly2.FullName.Contains("Telerik.WinControls.UI"))

                {

                    assembly = assembly2;

                    break;

                }

            }

            if (assembly != null)

            {

                Type type = assembly.GetType("Telerik.WinControls.UI.Licensing.RadEvaluationForm");

                object target = Activator.CreateInstance(type);

                type.InvokeMember("ShowDialog", BindingFlags.InvokeMethod, null, target, null);

            }

            else

            {

                using (EvaluationForm form = new EvaluationForm())

                {

                    form.ShowDialog();

                }

            }

            numberOfEvalMsgsShown++;

        }

    }

}

 
 
הקוד בודק האם יש רשיון (לא הצלחתי למצוא היכן הם מעדכנים את הערך של המשתנה licenceCount - ההימור שלי שהרשיון כנראה מביא איתו dll חדש ללא הפונקצייה הזאת - אבל אני לא בטוח)
לאחר מכן האם כבר הוצגו שלוש הודעות על גרסת הניסיון.
 
במידה ואין רשיון והם עדיין לא עצבנו את המפתח מספיק, הם בודקים האם ה dll שלהם טעון בזיכרון - במידה וכן הם יוצרים מופע של המסך שהצגתי למעלה ומפעילים אותו בעזרת Reflection, אחרת הם מציגים חלון אחר (דומה מאוד רק ללא עיצוב של telerik).
 
 
אחרי שמצאתי את הקוד - לעקוף אותו זה כבר עניין פשוט, היות שהחכמים האלו משתמשים ב - Reflection כדי לייצר את המופע - ויותר מכך הם בודקים האם ה - dll טעון לזיכרון לפי השם שלו, יצרתי dll חדש שקראתי לו Telerik.WinControls.UI.Crack, הוספתי לו את הקוד הבא:
 

namespace Telerik.WinControls.UI.Crack

{

    public class RadEvaluationForm

    {

        public static void Crack()

        {

 

        }

    }

}

 

namespace Telerik.WinControls.UI.Licensing

{

    public class RadEvaluationForm

    {

        public void ShowDialog()

        {

 

        }

    }

}

 
בפונקצית Main לפני הכול קראתי ל - Crack
 

RadEvaluationForm.Crack();

 
מה שקורה הוא שהיות שהשימוש בפונקציית Crack קורה לפני כל דבר אחר, ה - dll שלי (שכזכור עומד בבדיקה שהם עשו - Contain על השם שלו) נטען ראשון לזיכרון, ולכן כשהם יבקשו מופע של החלון הם יקבלו את המחלקה שלי שפונקציית ה - ShowDialog לא עושה כלום.
 
דרך אחרת - היא פשוט להריץ קוד שיבצע את הדבר הבא:
 

Type type = typeof(RadElementTree);

FieldInfo evalMsgInfo = type.GetField("numberOfEvalMsgsShown", BindingFlags.NonPublic | BindingFlags.Static);

evalMsgInfo.SetValue(null, 50);

 
 
ואז למעשה, נגרום להם לחשוב שהם כבר הציקו לנו מספיק.

שינוי ערכים של App Settings מתוך הקוד

 

 
כשעובדים עם מנגנון ה - Settings של net, ניתן בקלות לשנות את הערכים שלהם מתוך הקוד, אבל במידה שנשתמש במנגנון ה - appSettings ונרצה מתוך הקוד לשנות את הערך השמור בהם, נצטרך לעבוד טיפה יותר קשה - הקוד הבא מתאים לא רק ל - appSettings אלא לכל מקטע שנרצה לשנות מתוך הקוד.
 
 

Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

config.AppSettings.Settings["KEY"].Value = value;

config.Save(ConfigurationSaveMode.Modified);

ConfigurationManager.RefreshSection("appSettings");

 
 
כמובן שניתן להשתמש גם בפונקציות אחרות של ה - ConfigurationManager כדי לפתוח קבצי קונפיג של אפליקצייה אחרת.
 
פשוט וקל.
Posted: Mar 29 2012, 05:28 AM by Shlomo | with 1 comment(s)
תגים:,

List Control Editor

 

בהמשך לפוסט הקודם (חובה לקרוא לפני הפוסט הנוכחי) ננסה לשנות את ה - List Control Editor כך שיתאים לכמה Controls ולא רק ל - ListBox.
 
(את הקוד המלא ניתן להוריד כאן)
 
המחלקה ListBoxItem תהפוך ל - ListControlItem ותראה כך:
 

public class ListControlItem

{

    public string Name { get; set; }

    public string Value { get; set; }

 

    public override string ToString()

    {

        if (DesignMode)

        {

            if (Name == null && Value == null)

                return "ListBoxItem {}";

 

            return string.Format("{0}, {1}", Name, Value);

        }

 

        if (Name == null)

            return string.Empty;

 

        return Name;

    }

 

    private static Lazy<bool> _designMode =

        new Lazy<bool>(() =>

            Process.GetCurrentProcess().ProcessName.ToLower() == "devenv");

 

    private static bool DesignMode

    {

        get

        {

            return _designMode.Value;

        }

    }

}

 
השינויים (חוץ משינוי השם) זה הוספת הבדיקה בזמן ה - ToString האם אנחנו בזמן פיתוח או בזמן ריצה כדי לדעת איזה מחרוזת להחזיר, כדי לדעת האם אנחנו בזמן פיתוח נשתמש בבדיקה מיהו התהליך שמריץ את הקוד שלנו (לצערי לא מצאתי דרך הגיונית אחרת - אשמח לשמוע על דרך שונה).
 
המתודה AsEnumerable תיוצא למחלקה שתוסיף מתודות לכל מי שהוא IList ותיראה כך:
 

internal static class ListControlHelper

{

    internal static IEnumerable<object> AsEnumerable(this IList collection)

    {

        foreach (object item in collection)

        {

            yield return item;

        }

    }

 

    internal static void AddRange(this IList collection, Array items)

    {

        foreach (object item in items)

        {

            collection.Add(item);

        }

    }

}

 
 
המחלקה שיורשת מ - UITypeEditor לא תעשה casting ל - ObjectCollection אלא ל - IList, המתודה EditValue תראה כך:
 

public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)

{

    IWindowsFormsEditorService editorService = null;

 

    if (provider != null)

    {

        editorService = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;

    }

 

    if (editorService != null)

    {

        var selectionControl = new ListControlKeyValueCollectionControl((IList)value);

        editorService.ShowDialog(selectionControl);

    }

 

    return value;

}

 
 
ושוב את המחלקה של ListControlKeyValueCollectionControl (הטופס שמאפשר לערוך את המידע) אני לא מראה כאן, אבל הוא ניתן להורדה.
 
וכעת ניתן להשתמש גם עבור ComboBox (לדוגמא)
 

public class ValueComboBox : ComboBox

{

    [Category("Data")]

    [Editor("Controls.ListControlKeyValueCollectionEditor", typeof(UITypeEditor))]

    public new ComboBox.ObjectCollection Items

    {

        get

        {

            return base.Items;

        }

    }

}

Posted: Mar 15 2012, 09:39 PM by Shlomo | with no comments
תגים:,

ValueListBox - List Control Editor

 

 
אחד הפקדים ב - Windows Forms Application הוא - ListBox, הפקד יכול לקבל רשימה של אובייקטים ולהציג את הערך שחוזר מתוך ה - ToString.
 
יש לפקד רק בעייה אחת, מקוד ניתן לתת ל - ListBox כל אובייקט שנרצה, אבל ב - Design Time ניתן לתת לו רק מערך של מחרוזות (אלא אם כן נעבוד עם Binding), כשנלחץ על הלחצן של עריכת ה - Items נקבל את החלון הבא:
 
 
 
String Colection Editor
 
 
כמובן שהחלון הזה אינו מאפשר לתת ערכים שהם Key/Value.
 
לכן הייתי צריך לשנות קצת את המימוש של הפקד.
 
הסיבה שהחלון הזה קופץ בזמן לחיצה על ה - Items של הפקד, היא שכך נראה המאפיין Items של ListBox
 

[Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor", typeof(UITypeEditor))]

public ListBox.ObjectCollection Items { get; }

 
ה - Editor מגדיר מיהו החלון שיקפוץ בזמן עריכת ה - Items.
 
 
כעת נכתוב פקד משלנו, כל מה שנעשה הוא נדרוס את המימוש של המאפיין Items כשנשים עליו Editor משלנו.
 

public class ValueListBox : ListBox

{

    [Category("Data")]

    [Editor("Controls.ListControlKeyValueCollectionEditor", typeof(UITypeEditor))]

    public new ListBox.ObjectCollection Items

    {

        get

        {

            return base.Items;

        }

    }

}

 
נכתוב מחלקה קטנה המחזיקה Key/Value
 

public class ListBoxItem

{

    public string Name { get; set; }

    public string Value { get; set; }

 

    public override string ToString()

    {

        if (Name == null && Value == null)

            return "ListBoxItem {}";

 

        return string.Format("{0}, {1}", Name, Value);

    }

}

 
 
המחלקה דואגת גם שביצירת מופע חדש של ListBoxItem ה - ToString יחזיר ערך כלשהו עבור מי שצריך להציג אותו כל זמן שלא הוגדר Name, Value.
 
כעת גם נאפשר לייצר שאילתות Linq על Items (כפי שהוסבר בפוסט הזה) - נשתמש בזה מאוחר יותר
 

public static class ListBoxHelper

{

    public static IEnumerable<object> AsEnumerable(this ListBox.ObjectCollection collection)

    {

        foreach (object item in collection)

        {

            yield return item;

        }

    }

}

 
כמובן אנחנו צריכים לכתוב את ה - Editor שהגדרנו. כל ה - Editors צריכים לרשת מ - UITypeEditor, וכך הוא נראה:
 

public class ListControlKeyValueCollectionEditor : UITypeEditor

{

    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)

    {

        return UITypeEditorEditStyle.Modal;

    }

 

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)

    {

        IWindowsFormsEditorService editorService = null;

 

        if (provider != null)

        {

            editorService = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;

        }

 

        if (editorService != null)

        {

            var selectionControl = new ListControlKeyValueCollectionControl((ListBox.ObjectCollection)value);

            editorService.ShowDialog(selectionControl);

        }

 

        return value;

    }

}

 
במתודת GetEditStyle נחליט האם מדובר בהופעה של חלון או ב - DropDown, ובמתודת EditValue נציג את החלון.
 
המשתנה value מכיל את הערך של Items, כאן אנחנו מייצרים מופע של Form שכתבנו שנראה כך:
 
List Control Editor
 
 
הוא מקבל את ה - List ויודע להוסיף אליו ערכים. ה - Form הזה הוא טופס רגיל לכל דבר, אני לא מציג כאן את הקוד שלו, תוכלו להוריד את הדוגמא המלאה מהלינק בתחילת הפוסט כדי לראות את הקוד.
 
כפי שאפשר לראות לכתוב Editors משלנו זוהי לא תורה גדולה, ועם קצת עבודה ניתן לשכלל אפילו את הפקדים של מייקרוסופט.
Posted: Mar 14 2012, 02:13 PM by Shlomo | with 4 comment(s)
תגים:,

Cannot truncate table 'TableName' because it is being referenced by a FOREIGN KEY constraint.

 

כשרוצים למחוק מידע מטבלאות, לעיתים רוצים ממש לנקות את הטבלה, ובמידה ויש עמודת מספר רץ (נניח Id שמוגדר כ - Identity) נרצה לא רק למחוק את השורות, אלא גם לאפס את המספר הרץ כך שהמספור יתחיל מההתחלה.
 
הצורה הפשוטה היא להשתמש ב - truncate במקום delete, כך:
 

truncate table Color

 
הבעייה תהיה, במידה ויש קשר בין טבלה זו לטבלאות אחרות נקבל את הודעת השגיאה הבאה: Cannot truncate table 'Color' because it is being referenced by a FOREIGN KEY constraint.
 
 
כדי לאפס בכל זאת את המספר הרץ, נכתוב את הקוד הבא
 

delete from Color

DBCC CHECKIDENT (Color, RESEED, 0)

 
כעת המידע ימחק, והשורה הבאה שתיכנס תהיה עם הערך 1 בעמודת Id.

Install SMTP server in IIS (on Windows Server 2008) - Setp By Step

 

בפוסט הזה כתבתי כיצד לשלוח מייל מקוד (אפילו התחכמתי שם ועשיתי את זה מ - JS), מסתבר שלהתקין SMTP על השרת הוא גם סרט לא קטן למי שלא מכיר את התהליך - שרפתי כמה שעות טובות על נסיונות ההגדרה של השרת, ופוסט זה נועד לחסוך את השעות הלוו למי שצריך לעבור את התהליך.
 
 
השלבים שצריך לעשות כדי לאפשר שליחת מיילים.
1. התקנה של IIS.
2. התקנה של SMTP.
3. הפעלת ה - SMTP Service.
4. קינפוג של ה - SMTP Service.
5. פתיחת פורט ה - SMTP בחומת האש.
 
 
אחד הדברים השונים ב - Windows Server הוא חלוקה של Roles ו - Feature. כדי להתקין IIS נצטרך להיכנס ל - Roles ולהוסיף את IIS.
ב - Server Manager בחרו ב - Roles ולחצו על Add Roles, בחרו ב - Web Server (IIS. וודאו שאתם מתקינים גם את IIS 6.
 
לאחר מכן תחת Add Feature התקינו את SMTP Server.
 
משום מה מישהו החליט שגם אם התקינו את השירות אנחנו לא בוודאות רוצים להפעיל אותו, ולכן נגיע ל - Services ונפעיל את ה - Simple Mail Transfer Protocol (וכנראה כדאי לשנות את ההגדרה להפעלה אוטומטית).
 
בתוך IIS יש לבחור ב - SMTP E-mail, נסמן את deliver email to smtp server, נסמן את localhost ונבחר את הפורט (25 הוא ברירת המחדל).
 
בשלב הבא נפתח את IIS 6.0 Manager (ניתן להגיע אליו על ידי כתיבה של המילה IIS ב - Start, במידה ולא התקנתם אותו צריך להוסיף אותו בהתקנה של IIS.
 
קליק ימין על SMTP Virtual Server ובחירה ב - Properties, בטאב של Access לחצו על Relay והוסיפו את כתובת ה - IP של 127.0.0.1.
 
כל מה שנשאר הוא לפתוח את הפורט בחומת האש (אם קיימת כזאת). ויש לכם שרת מייל.
 
בהצלחה